SwiftUI(macOS)全局键盘事件触发时能否禁用funk错误提示音
问题原因
你使用的NSEvent.addGlobalMonitorForEvents仅支持监听全局按键事件,不具备拦截、消费事件的能力。系统检测到F3/F4按键事件没有被任何活跃应用响应,就会触发默认的funk错误提示音。
解决方案
推荐使用CGEventTap实现全局按键的捕获与消费,你代码中已经申请了辅助功能权限,可以直接适配,修改步骤如下:
- 在AppDelegate中新增属性存储事件监听端口
class AppDelegate: NSObject,NSApplicationDelegate { var statusItem: NSStatusItem! var popOver: NSPopover! // 新增属性 var eventTap: CFMachPort? // ... 原有其他代码
- 替换原有的NSEvent全局监听代码
把原来的NSEvent.addGlobalMonitorForEvents整块代码替换为以下实现:
// 监听全局键盘按下事件 let eventMask = (1 << CGEventType.keyDown.rawValue) guard let eventTap = CGEvent.tapCreate( tap: .cgSessionEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: CGEventMask(eventMask), callback: { proxy, type, event, refcon in guard type == .keyDown else { return Unmanaged.passRetained(event) } let keyCode = event.getIntegerValueField(.keyboardEventKeycode) // 匹配目标按键F3(99)、F4(118) if keyCode == 99 || keyCode == 118 { // 你原来的按键处理逻辑 if keyCode == 99 { // 处理F3按下逻辑 } else if keyCode == 118 { // 处理F4按下逻辑 } // 返回nil代表消费当前事件,不再向下传递,不会触发系统提示音 return nil } // 非目标按键正常传递给系统 return Unmanaged.passRetained(event) }, userInfo: nil ) else { print("事件监听创建失败,请确认已开启应用的辅助功能权限") return } self.eventTap = eventTap // 将监听器加入当前运行循环 let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes) CGEvent.tapEnable(tap: eventTap, enable: true)
注意事项
- 首次运行需要在弹出的权限申请窗口中跳转到系统设置,给应用开启辅助功能权限,重启应用后生效
- 如果你需要保留系统F3/F4的默认功能(如调度中心、启动台),不需要拦截事件的话,把
return nil改为return Unmanaged.passRetained(event),同时到系统设置>键盘>快捷键中关闭F3/F4对应的默认绑定即可消除提示音 - 你原有代码中的NSEvent监听部分存在多余的闭合大括号,替换后可以修复该语法问题
内容的提问来源于stack exchange,提问作者tstamatakis
相关产品推荐
相关产品推荐

