如何在不编码窗口状态的情况下以编程方式终止 NSApp?

Posted

技术标签:

【中文标题】如何在不编码窗口状态的情况下以编程方式终止 NSApp?【英文标题】:How to programmatically terminate NSApp without encoding window state? 【发布时间】:2016-06-12 23:39:17 【问题描述】:

所有支持NSWindowRestoration 的 OS X 应用程序都可以通过选择菜单项“退出并关闭所有窗口”(Option-Command Q)来关闭。这将禁用状态恢复,并且下次打开应用程序时所有窗口都将处于默认位置。

菜单项触发NSApplication 上的terminate: 方法。但是常规的“关闭应用程序”菜单也是如此(命令 Q)。

如何以编程方式执行“退出并关闭所有窗口”?我真的必须自己关闭所有窗口然后调用terminate:吗?

当两个操作都连接到同一个terminate: 方法时,Apple 如何神奇地决定要做什么?

【问题讨论】:

你为什么不直接在终止窗口时循环并关闭它们? @l'L'l 因为这将是额外的代码来管理,而 Apple 有一个使用简单方法调用的解决方案。 【参考方案1】:

似乎没有一个很好的方法来做到这一点。您可能想向 Apple 提交错误请求(并说明您需要它的原因)。

当两个操作都连接到同一个terminate: 方法时,Apple 如何神奇地决定要做什么?

好吧,看看 AppKit 的反汇编,-[NSApplication terminate:] 似乎检查了发件人是否是NSMenuItem 的实例。如果是,则检查其userInterfaceItemIdentifier 是否等于@"NSAlternateQuitMenuItem"

我想,您可以使用该标识符创建一个虚拟菜单项,并将其作为发送者传递给 -terminate:,尽管由于这依赖于实现细节,它可能随时中断。

另一个控制因素是系统偏好设置>常规>“退出应用程序时关闭窗口”的设置。这对应于用户默认键NSAlternateQuitMenuItem,尽管这又是一个实现细节。看来您可以在调用-terminate: 之前设置它,然后在-applicationWillTerminate: 委托方法中删除该设置。 (您的更改将与您的应用程序相关联。它们不会影响其他应用程序或系统偏好设置中的设置。)当然,您必须确保禁用突然终止以获取该委托方法调用。

【讨论】:

我不知道,NSMenuItem 上有一个userInterfaceItemIdentifier 属性。我刚刚在 Objective-C 中创建了必要的接口定义来访问它。非常感谢! 提出了一些进一步的调查,这是唯一获得此类标识符的菜单项。它最初不存在,但在应用启动一段时间后自动添加。 整个菜单项“最初”并不存在。它是由 Cocoa 在设置主菜单时创建的。如果您要依赖此具有特定标识符的菜单项,那就太糟糕了。绝对不要依赖它是唯一具有标识符的项目。 当然,我只是想确保不再有我可能错过的魔法。我目前只本地化应用程序的菜单,有趣的是,甚至“显示工具栏”和“隐藏工具栏”之间的自动文本替换也依赖于 Apple 为每种语言选择的完全相同的措辞。

以上是关于如何在不编码窗口状态的情况下以编程方式终止 NSApp?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 UINavigationController 的情况下以编程方式进入 rootViewController

如何在不“连接”它们的情况下以编程方式访问 NIB 中的 UI 元素?

如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)

如何在不使用外部主机的情况下以编程方式查找设备的外部 IP 地址?

如何在不使用第三方的情况下以编程方式从 Chase 下载我的银行交易?

如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面?