SwiftUI macOS菜单栏应用如何通过键盘快捷键唤起NSPopover
你当前用SwiftUI Commands 配置的快捷键仅在应用处于激活状态时才会响应,要实现用户在任意操作场景下都能触发快捷键打开Popover,需要使用全局键盘事件监听方案,具体修改步骤如下:
步骤1:新增全局快捷键监听逻辑
首先在AppDelegate中添加全局事件监听、权限校验相关代码,完整修改后的AppDelegate核心代码如下:
import CoreGraphics import AppKit class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { var popover = NSPopover.init() var statusBarItem: NSStatusItem? var contentView: ContentView! // 存储全局监听对象 private var hotKeyMonitor: Any? override class func awakeFromNib() {} func applicationDidFinishLaunching(_ notification: Notification) { print("Application launched") NSApplication.shared.activate(ignoringOtherApps: true) contentView = ContentView() popover.animates = false popover.behavior = .transient let contentVc = NSViewController() contentVc.view = NSHostingView(rootView: contentView.environmentObject(self)) popover.contentViewController = contentVc statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) let itemImage = NSImage(named: "statusBarIcon") itemImage?.isTemplate = true statusBarItem?.button?.image = itemImage statusBarItem?.button?.action = #selector(AppDelegate.togglePopover(_:)) // 新增:校验辅助功能权限,注册全局快捷键监听 let accessCheckOptions: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] let isAccessGranted = AXIsProcessTrustedWithOptions(accessCheckOptions) if isAccessGranted { registerGlobalHotKey() } } // 新增:注册全局快捷键 private func registerGlobalHotKey() { hotKeyMonitor = NSEvent.addGlobalMonitorForEvents(matching: .keyDown) { [weak self] event in guard let self = self else { return } // 这里可以替换为你想要的任意字母,比如改为"k"就是Command+K触发 guard event.modifierFlags.contains(.command), event.characters == "p", // 避免和应用内快捷键冲突:应用激活且Popover已打开时不触发 !(NSApplication.shared.isActive && self.popover.isShown) else { return } self.togglePopover(nil) } } // 新增:退出时移除监听 func applicationWillTerminate(_ notification: Notification) { if let monitor = hotKeyMonitor { NSEvent.removeMonitor(monitor) } } @objc func showPopover(_ sender: AnyObject?) { if let button = statusBarItem?.button { NSApplication.shared.activate(ignoringOtherApps: true) popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY) } } @objc func closePopover(_ sender: AnyObject?) { popover.performClose(sender) } @objc func togglePopover(_ sender: AnyObject?) { if popover.isShown { closePopover(sender) } else { showPopover(sender) } } }
注意事项
- 第一次启动应用时会弹出辅助功能权限申请提示,用户需要在「系统设置>安全性与隐私>隐私>辅助功能」中勾选你的应用,权限生效后全局快捷键才可正常使用
- 你可以自行修改
registerGlobalHotKey方法中event.characters == "p"的取值,替换为你想要绑定的任意字母,注意避开系统全局占用的快捷键即可 - 原有
MenuBarPopoverCommands中配置的编辑类快捷键不受影响,仅在Popover打开、应用激活时正常响应
内容的提问来源于stack exchange,提问作者Rohan
相关产品推荐
相关产品推荐

