如何关闭应用后隐藏Dock中的图标?排除LSUIElement及accessory激活策略
解决方案:关闭应用后隐藏Dock图标(保留运行时的图标与主菜单)
嘿,我正好碰到过完全一样的需求,折腾了好一阵终于找到完美的解决办法,完全符合你说的「运行时保留Dock图标和主菜单,关闭后隐藏(包括最近使用列表)」的要求,给你拆解一下:
核心思路
我们需要动态切换应用的激活策略,根据应用的当前状态调整:
- 当应用有窗口显示时:保持激活策略为
.regular,这样Dock图标正常显示,主菜单也能正常使用。 - 当所有窗口关闭(或应用即将退出)时:切换到
.prohibited,让Dock不再显示该应用的图标,同时避免被加入最近使用列表。
具体代码实现
1. 窗口关闭后的状态切换
在AppDelegate里监听窗口关闭事件,当最后一个窗口关闭时切换激活策略:
import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { private var activeWindowCount = 0 func applicationDidFinishLaunching(_ aNotification: Notification) { // 初始化当前窗口数量 activeWindowCount = NSApplication.shared.windows.count } func applicationWillClose(_ notification: Notification) { guard notification.object is NSWindow else { return } activeWindowCount -= 1 // 最后一个窗口关闭时,切换到禁止显示的策略 if activeWindowCount == 0 { NSApp.setActivationPolicy(.prohibited) } } // 示例:从状态栏/菜单栏重新打开窗口时,切回正常策略 func reopenMainWindow() { let mainWindow = NSWindow( contentRect: NSRect(x: 200, y: 200, width: 800, height: 600), styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: false ) mainWindow.contentViewController = YourMainViewController() mainWindow.makeKeyAndOrderFront(nil) activeWindowCount += 1 NSApp.setActivationPolicy(.regular) NSApp.activate(ignoringOtherApps: true) } }
2. 应用退出时的隐藏处理
为了确保退出后不会出现在Dock的最近使用列表里,在退出前切换策略:
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { NSApp.setActivationPolicy(.prohibited) return .terminateNow }
关键细节解释
- 为什么不能用
LSUIElement?这个属性会让应用全程不在Dock显示,完全违背你“运行时保留图标”的需求。 - 为什么不用
.accessory激活策略?.accessory会直接移除应用的主菜单,而我们需要运行时主菜单正常可用,.regular才是正确的选择。 .prohibited策略的作用:它会让应用立刻从Dock中消失,同时系统不会把它加入最近使用列表,完美解决关闭后的隐藏需求。
额外体验优化
如果你的应用有状态栏图标,可以把reopenMainWindow方法绑定到状态栏图标的点击事件上,这样用户在隐藏窗口后还能快速唤起应用,体验会更流畅。
内容的提问来源于stack exchange,提问作者aleksid1
相关产品推荐
相关产品推荐

