如何避免macOS Swift文档应用中浮动Palette窗口被当作文档触发Cmd-N新建
问题根因
该问题由macOS默认的主窗口响应链优先级逻辑触发:
- 普通
NSWindow的canBecomeMain属性默认值为true,浮动Palette窗口被激活后会成为应用的主窗口(main window) - 主菜单Cmd-N绑定的
newDocument:动作会优先发送给当前主窗口的响应链,你的Palette窗口所属控制器没有实现该方法,系统就会触发默认的「新建同类型窗口」逻辑,生成多余的浮动窗口副本 - 手动激活文档窗口后,文档窗口重新成为主窗口,
newDocument:动作正常交给NSDocumentController处理,新建文档逻辑恢复正常
最佳实现方案
方案1(推荐,符合系统交互规范)
浮动工具类窗口本身就不应该成为应用主窗口,直接将Palette窗口的canBecomeMain属性设为false即可解决问题,不需要修改其他业务逻辑。
你可以直接在Storyboard的Palette窗口属性面板中取消勾选「Can Become Main」选项,也可以通过代码配置:
// 在Palette对应的WindowController的windowDidLoad生命周期方法中添加 window?.canBecomeMain = false
配置完成后,就算Palette被激活成为接收键鼠事件的key window,应用的主窗口仍然是之前的文档窗口,Cmd-N动作会正常发送给文档响应链,不会再触发浮动窗口新建逻辑。
方案2(适配特殊需求场景)
如果你的业务场景要求Palette必须支持成为主窗口,直接在Palette对应的WindowController中实现newDocument:方法,手动转发动作给文档控制器即可:
override func newDocument(_ sender: Any?) { NSDocumentController.shared.newDocument(sender) }
内容的提问来源于stack exchange,提问作者jsbox
相关产品推荐
相关产品推荐

