Swift macOS开发:如何让窗口始终置顶并阻止后台应用获取焦点?
解决Mac Swift应用窗口始终置顶且阻止焦点窃取的问题
嘿,作为Mac开发新手碰到这个需求太正常了!你之前的代码确实能在窗口失去激活时把它拉回顶层,但还是会给后台应用短暂获取焦点的机会——这是因为applicationDidResignActive是在应用已经失去焦点后才触发的,中间会有个时间差。下面给你一套完整的解决方案:
1. 提升窗口层级,确保始终置顶
首先得让你的窗口稳稳站在所有普通窗口之上,我们可以设置它的level为浮动窗口层级(如果怕被其他浮动窗口盖住,还可以用更高层级):
在applicationDidFinishLaunching里添加配置:
func applicationDidFinishLaunching(_ aNotification: Notification) { guard let window = window else { return } // 设置窗口为浮动层级,确保在普通窗口上方 window.level = .floatingWindowLevel // 可选:如果要压过其他浮动窗口,用更高层级 // window.level = NSWindow.Level.mainMenuWindowLevel + 1 // 让窗口成为主窗口并强制显示 window.makeKeyAndOrderFront(nil) // 立即激活应用 NSApp.activate(ignoringOtherApps: true) }
2. 阻止应用被隐藏
默认情况下,用户按Command+H或者点击Dock里的其他应用,你的应用会被隐藏,我们直接禁用这个行为:
func applicationShouldHide(_ sender: NSApplication) -> Bool { // 返回false,禁止应用被隐藏 return false }
3. 提前拦截焦点丢失,不给后台应用机会
把之前的applicationDidResignActive换成applicationWillResignActive——在应用即将失去焦点时就立即重新激活,彻底堵死后台应用抢焦点的可能:
func applicationWillResignActive(_ notification: Notification) { DispatchQueue.main.async { // 重新激活应用 NSApp.activate(ignoringOtherApps: true) // 确保窗口保持在最前面并成为主窗口 self.window?.makeKeyAndOrderFront(nil) } }
4. 可选:让窗口在所有桌面空间都显示
如果希望切换桌面空间时窗口也能保持置顶,给窗口加这个配置:
window.collectionBehavior = .canJoinAllSpaces
这样组合下来,你的窗口就会死死钉在最顶层,用户点击窗口外区域时,应用会瞬间重新激活,后台应用根本没机会拿到焦点,完美实现你的需求!
内容的提问来源于stack exchange,提问作者Julian Cimentarow




