Xcode 9中使用NSApp.terminate()退出时窗口自动保存功能失效?
这绝对不是正常行为,问题出在应用退出时的状态保存时机上——Xcode停止按钮退出时,AppKit会触发调试模式下的特殊清理逻辑,帮你自动保存了窗口状态;但用Command+Q或手动调用NSApp.terminate(nil)时,默认流程可能跳过了窗口状态的主动保存步骤。
下面是你可能遗漏的配置和修复方案:
1. 确认窗口的可恢复性开关
先检查Storyboard里的窗口设置:选中你的窗口,打开Attributes Inspector,确保Restorable选项是勾选状态(默认应该是,但有时候会被意外取消)。如果用代码创建窗口,也要手动设置:
window.isRestorable = true
2. 让AppKit完成正常的退出流程
直接调用NSApp.terminate(nil)会强制终止应用,AppKit来不及执行窗口状态的保存逻辑。正确的做法是通过应用代理的退出回调,让系统自动处理保存:
实现NSApplicationDelegate的applicationShouldTerminate(_:)方法,返回.terminateNow即可——这个方法会告诉AppKit在终止前完成所有必要的清理(包括窗口状态保存):
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { // 这里可以添加自定义的退出前逻辑,比如保存用户数据 return .terminateNow }
如果之前你是直接调用NSApp.terminate(nil),改成调用NSApp.reply(toApplicationShouldTerminate: true)(前提是先触发了applicationShouldTerminate的询问流程)。
3. 手动强制保存窗口状态(可选)
如果上面的方法还是不行,可以在退出前手动触发窗口状态的保存,确保万无一失:
func applicationWillTerminate(_ notification: Notification) { NSApplication.shared.windows.forEach { window in guard let autosaveName = window.autosaveName else { return } if window.isRestorable { window.saveFrame(usingName: autosaveName) } } }
这个方法会遍历所有可恢复窗口,手动把它们的位置和大小保存到偏好设置里。
为什么Xcode停止按钮能正常工作?
Xcode停止调试时,会向应用发送SIGSTOP信号,AppKit在处理进程终止时,会触发一套调试模式下的清理流程,其中就包含了窗口状态的自动保存。但正常退出时,这个触发逻辑不会自动执行,需要我们主动让AppKit走正常的退出流程。
内容的提问来源于stack exchange,提问作者Jay Wang

