SwiftUI macOS菜单:如何实现带复选标记与快捷键的可选菜单项?
问题解答
这是SwiftUI在macOS上的已知限制,当使用.inline样式的Picker包裹带keyboardShortcut的Button时,Picker会拦截按钮的快捷键绑定,导致快捷键失效。并非你的操作有误。
替代方案1:用Menu + Toggle实现(推荐)
放弃Picker,直接用Menu结合Toggle组件,既能实现复选标记,又能正常绑定快捷键:
@State private var selection = 1 Menu("自定义菜单") { Toggle("Test 1", isOn: Binding( get: { selection == 1 }, set: { _ in selection = 1 } )) .keyboardShortcut("1") Toggle("Test 2", isOn: Binding( get: { selection == 2 }, set: { _ in selection = 2 } )) .keyboardShortcut("2") }
这种方式利用Toggle的选中状态模拟单选/多选效果,同时快捷键可以正常触发。如果是单选场景,通过绑定的get/set逻辑确保同一时间只有一个选项被选中。
替代方案2:结合AppKit手动添加快捷键(适合坚持用Picker的场景)
如果必须使用Picker,可以通过AppKit的NSMenuItem手动为对应的动作添加全局快捷键,绕开SwiftUI的限制:
@State private var selection = 1 @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { // 为Test 1添加快捷键 let test1MenuItem = NSMenuItem(title: "Test 1", action: #selector(test1Action), keyEquivalent: "1") test1MenuItem.keyEquivalentModifierMask = [] // 可根据需求添加Command/Shift等修饰符 NSApp.mainMenu?.item(withTitle: "你的菜单栏名称")?.submenu?.addItem(test1MenuItem) } @objc func test1Action() { // 更新SwiftUI的selection状态 let contentView = NSApp.windows.first?.contentViewController as? NSHostingController<ContentView> contentView?.rootView.selection = 1 } } // ContentView中的Picker部分 Picker(selection: $selection) { Button("Test 1") {} .tag(1) }.pickerStyle(.inline)
这种方式需要手动管理AppKit的菜单层级,适合对原有Picker结构依赖较强的场景,但代码复杂度更高。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

