Swift macOS开发中如何判断Safari是否处于前台激活状态
实现方法
你提到的NSWorkspace和NSRunningApplication就是实现这个需求的正确方案,CGWindowList本身不提供应用激活状态的判断能力,不需要遍历全量窗口列表来做前台应用检测,直接调用系统封装好的接口准确率更高、性能开销更低。
核心逻辑非常直接:
- 通过
NSWorkspace.shared.frontmostApplication直接获取当前处于前台激活状态的应用 - 不要用应用名称做匹配判断:应用名存在多语言本地化改名、重名应用的问题,直接判断应用的固定Bundle ID即可,Safari的官方Bundle ID为
com.apple.Safari - 你原有代码中对
kCGWindowOwnerName的as!强制类型转换存在崩溃风险,建议避免使用强制解包
修改后的可运行代码如下:
func applicationDidFinishLaunching(_ aNotification: Notification) { NSEvent.addGlobalMonitorForEvents(matching: .otherMouseDown) { event in print("鼠标按键按下,按钮编号:\(event.buttonNumber)") // 直接获取当前前台激活应用 guard let frontmostApp = NSWorkspace.shared.frontmostApplication else { return } // 判断前台应用是否为Safari if frontmostApp.bundleIdentifier == "com.apple.Safari" { print("Safari处于前台激活状态,执行后续逻辑") // 如果后续仍需要获取Safari的窗口信息,再调用CGWindowList接口即可 let options = CGWindowListOption(arrayLiteral: .excludeDesktopElements, .optionOnScreenOnly) if let windowListInfo = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: Any]] { // 通过kCGWindowOwnerPID匹配前台应用进程ID,过滤出属于当前前台Safari的窗口 let safariPID = frontmostApp.processIdentifier let safariWindows = windowListInfo.filter { windowInfo in guard let windowPID = windowInfo[kCGWindowOwnerPID as String] as? pid_t else { return false } return windowPID == safariPID } print("Safari当前在屏窗口数量:\(safariWindows.count)") } } } }
注意事项
- 全局鼠标事件监控需要你的应用在系统设置的「隐私与安全性-辅助功能」中获得用户授权,否则无法收到全局的鼠标按键事件
- 如果你只需要判断Safari是否在前台,完全不需要调用
CGWindowListCopyWindowInfo接口,上面的前台应用判断逻辑已经可以满足需求 - 如果需要兼容非系统默认安装路径的Safari,Bundle ID判断的方式依然生效,比匹配应用名可靠得多
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

