2

我正在构建一个带有主窗口和子窗口的应用程序,我想将其作为模式会话呈现。所以我在窗口控制器中使用这段代码:

self.session = [[NSApplication sharedApplication] beginModalSessionForWindow: self.window];
[[NSApplication sharedApplication] runModalSession: self.session];

然而,不管我把这段代码放在哪里——在windowDidLoad中,在来自主窗口的post-windowDidLoad调用中,甚至在窗口控制器的init函数中——我得到的是一个无模式的子窗口。子窗口出现在主窗口上方,但主窗口继续响应输入事件。

我究竟做错了什么?

4

1 回答 1

3

nvm - 通过阅读一些示例找到了我的答案。(再一次,在 Stack 上发布之前数小时的研究未能产生答案,我在发布后就偶然发现了洞察力。)

对于后代,这是答案:beginModalSessionForWindow 不像 runModalForWindow 那样工作。

使用 runModal,您可以在任何地方执行该代码,Cocoa 将立即停止除模式窗口之外的所有处理。(不幸的是,这包括与用于后台处理的非 UI 事件相关联的计时器。)执行 runModal 的代码被阻止,并且只有在模式窗口关闭后才能恢复。系统强制执行窗口的模态。

beginModalSessionForWindow 的工作方式非常不同。无论你在哪里执行它,代码都会启动模态窗口,然后继续执行。在一般用例中(如 Apple 的示例所示),如果您在循环之前调用 beginModal,然后在轮询会话状态时为循环设置条件,则循环可以执行您想要的任何其他处理;在循环期间,它还会阻止正常的 UI 事件——就像任何 IBAction 在执行长时间运行的循环时一样。

关键是 beginModalSession 实际上并不强制执行窗口的任何模式。相反,您的代码通过执行长时间运行的循环来强制执行窗口的模式。如果您不使用循环,而只是让“模态”会话运行并恢复普通事件循环......那么您的其他窗口将获得所有事件处理,包括 UI 事件。“模态”窗口变为无模态。

我会争辩说“beginModalSessionForWindow”真的应该被称为beginModelessSessionForWindow,因为这就是它的作用:它创建一个无模式窗口并返回。

于 2012-09-27T18:50:43.393 回答