随着Pharo 13正式版发布,新一代UI框架Spec 2已全面取代旧版Spec 1,成为构建桌面应用的标准工具。然而,许多从旧项目迁移而来的开发者发现,曾经熟悉的openWorldWithSpec方法似乎“消失”了。近日,Pharo社区中一条帖子引发热议:“Is there a Spec 2 presenter method corresponding to openWorldWithSpec from Spec 1 in Pharo 13?” 这背后折射出迁移过程中一个普遍的困惑——Spec 2究竟如何打开一个顶层窗口?本文将深入技术细节,为开发者厘清正确的实现路径。

旧世界的记忆:Spec 1中的openWorldWithSpec

在Spec 1时代,openWorldWithSpec是Presenters中一个极为便捷的方法。它允许开发者在没有显式创建Application或Window对象的情况下,直接打开一个包含指定Presenter内容的独立窗口。例如,只需一行代码:

MyPresenter new openWorldWithSpec

即可让MyPresenter以顶层窗口的形式呈现在Pharo的世界(World)中。这种方式非常类似于Smalltalk传统的“打开一个Morph”思维,简捷但缺乏对窗口行为的精细化控制。正因如此,Spec 2在设计时决定抛弃这种“开箱即用”的模式,转而采用更严格的架构:每一个顶层窗口都应当由SpApplication管理,窗口和Presenter的关系必须显式定义。

Spec 2的哲学:从“快速打开”到“应用导向”

Spec 2重新定义了UI组件的生命周期。在新框架中,Presenter不再自己决定如何打开,而是由Application负责创建窗口、设置标题、图标、关闭行为等。官方文档明确建议:永远不要直接创建SpWindow,而是通过Application的newWindow:或Presenter的openWithSpec方法。但问题来了——openWithSpec不会像openWorldWithSpec那样自动产生一个独立窗口,它默认将Presenter嵌入到当前已有的窗口中(例如一个Workspace或工具窗口)。

那么,Spec 2中到底有没有一个与openWorldWithSpec等价的一行代码解决方案?答案是:有,但方法名变了,且需要理解背后的抽象

找到替代方法:openWithSpec in a new window

若要在Spec 2中实现“直接打开一个Presenter作为独立窗口”,最接近的写法是使用#openWithSpec的变体——#newApplication#newWindowPresentation组合,或者更常用的:直接使用Presenter类的类方法open

具体而言,Pharo 13的Spec 2为Presenter类和其元类添加了一个名为open的类方法,该方法自动创建一个临时Application,并将当前Presenter以独立窗口打开。用法如下:

MyPresenter open

这行代码会做三件事:实例化一个SpApplication,调用newWindow:配置窗口,并启动UI循环。它本质上等价于Spec 1的openWorldWithSpec,但封装得更符合Spec 2的架构。

此外,如果你需要自定义窗口属性(如标题、大小),可以使用:

MyPresenter new openWithSpec

但请注意,这个方法要求窗口已经存在。真正能创建新窗口的是#open类方法,或者显式地通过SpApplication

app := SpApplication new.
app newWindow: (app newPresenter: MyPresenter new).
app run.

社区实践与迁移建议

在Pharo社区论坛的讨论中,多位核心开发者指出:openWorldWithSpec在Spec 2中确实没有直接的同名方法,但MyClass open就是官方推荐的替代方案。他们还提醒,旧代码中大量使用openWorldWithSpec的地方,往往忽略了窗口生命周期管理,导致资源泄漏或状态混乱。迁移时应尽可能重构为Application驱动的方式。

对于需要向后兼容的场景,可以编写一个简单的扩展方法,例如:

SpPresenter class >> openWorldWithSpec
    ^ self new openWithSpec

但要注意,这种方法在Spec 2中不会自动设置Application,可能导致某些事件(如窗口关闭处理)失效。因此,更好的做法是直接使用open

结论

Spec 2去除了openWorldWithSpec,但并未剥夺开发者快速打开窗口的能力。MyPresenter open正是那个“缺失的方法”。从Spec 1到Spec 2的迁移不仅是方法名的变化,更是架构思路的升级——从“随手打开”到“应用管理”。对于Pharo 13的开发者而言,理解这一转变,将帮助你在新框架下编写更健壮、更可维护的UI代码。

Pharo 13已来,Spec 2已就位,是时候用open拥抱未来了。