You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift命令行应用NSEvent全局鼠标键盘事件监听失效问题

问题根本原因
  • 命令行Target默认不会启动AppKit依赖的主事件循环(NSRunLoop common模式下的主派发循环)。NSEvent.addGlobalMonitorForEvents的事件派发完全依赖AppKit主事件循环,而NSWorkspace.notificationCenter的消息派发不依赖该循环,因此这部分通知可以正常触发。
  • 事件监视器未被强持有:addGlobalMonitorForEvents返回的监视器对象如果没有被强引用,会在方法返回后被ARC立即回收,监听逻辑直接失效,这是AppKit事件监听的常见问题。
  • 代码存在Selector不匹配问题:注册工作区通知时传入的selector是logNotification,但给出的实现中只有logEvent和setInactive两个@objc方法,这部分通知即使触发也无法走到你写的日志逻辑。
  • 所有AppKit相关的事件监听逻辑必须在主线程调用,后台线程初始化监听不会生效。
修复步骤
  • 第一步:初始化NSApplication实例,配置合适的激活策略,避免Dock出现多余图标。在所有监听逻辑执行前加入以下代码:
import AppKit
// 初始化共享应用实例
let app = NSApplication.shared
// 使用accessory策略,不在Dock和Cmd+Tab切换列表显示,适合后台命令行工具
app.setActivationPolicy(.accessory)
  • 第二步:用数组或属性强持有所有事件监视器,避免被ARC释放:
// 定义全局/类属性存储监视器,保证生命周期和应用一致
var globalEventMonitors = [Any]()

// 注册监听时保存返回值
if let keyDownMonitor = NSEvent.addGlobalMonitorForEvents(matching: .keyDown, handler: logEvent) {
    globalEventMonitors.append(keyDownMonitor)
}
if let mouseMoveMonitor = NSEvent.addGlobalMonitorForEvents(matching: .mouseMoved, handler: logEvent) {
    globalEventMonitors.append(mouseMoveMonitor)
}
  • 第三步:修正工作区通知的Selector匹配问题,把注册时的selector替换为你实际实现的方法名,或者补全对应方法:
let workspaceNC = NSWorkspace.shared.notificationCenter
workspaceNC.addObserver(self, selector: #selector(setInactive), name: NSWorkspace.willSleepNotification, object: nil)
workspaceNC.addObserver(self, selector: #selector(setInactive), name: NSWorkspace.willPowerOffNotification, object: nil)
workspaceNC.addObserver(self, selector: #selector(setInactive), name: NSWorkspace.screensDidSleepNotification, object: nil)
workspaceNC.addObserver(self, selector: #selector(setInactive), name: NSWorkspace.sessionDidResignActiveNotification, object: nil)
  • 第四步:启动主事件循环,保证事件持续派发。注意这行代码会阻塞当前线程,要放在所有初始化逻辑的最后执行:
app.run()

额外校验点:确认辅助功能权限授予的是你当前运行的可执行文件,Xcode调试时每次build产物路径变化可能导致权限失效,需要在「系统设置-隐私与安全性-辅助功能」里删除旧的权限条目,重新运行应用授权即可。

内容的提问来源于stack exchange,提问作者Silve2611

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 19:39:19