SwiftUI中如何移除、替换、添加菜单(XCode12.4/MacOS11.1含AppDelegate的Mac应用)
适配Xcode 12.4 + macOS 11.1环境的SwiftUI Mac自定义菜单实现
核心前提
在你当前使用的版本中,SwiftUI 原生的菜单定制能力(.commands修饰符)尚未在 macOS 11 中推出,纯 SwiftUI 语法无法完成系统默认菜单的移除与替换,必须通过 AppDelegate 操作 AppKit 层的原生主菜单对象实现。
关键注意事项
- 操作时机必须选在
applicationWillFinishLaunching回调中:这个节点早于 SwiftUI 框架自动挂载系统默认菜单的流程,如果在applicationDidFinishLaunching中修改菜单,会被框架后续生成的「文件/编辑/视图/窗口/帮助」等默认菜单直接覆盖,自定义效果完全看不到。 - 主菜单中最顶部和 App 同名的应用专属菜单(包含关于、隐藏、退出选项)必须保留,缺失该结构会触发 macOS 菜单栏校验异常,导致快捷键失效、菜单显示错乱。
具体实现代码
直接修改你现有 AppDelegate 的逻辑,在 applicationWillFinishLaunching 中加入菜单重写逻辑即可,完整可运行代码如下:
class AppDelegate: NSObject, NSApplicationDelegate { func applicationWillFinishLaunching(_ notification: Notification) { // 原有窗口配置逻辑 NSWindow.allowsAutomaticWindowTabbing = false // 自定义菜单逻辑 guard let mainMenu = NSApp.mainMenu else { NSApp.mainMenu = NSMenu() return } // 取出必须保留的应用根菜单 guard let appRootMenu = mainMenu.items.first else { return } // 清空主菜单下所有默认生成的条目 mainMenu.removeAllItems() // 重新加回应用根菜单 mainMenu.addItem(appRootMenu) // 示例1:自定义偏好设置菜单 let prefsSubmenu = NSMenu(title: "偏好设置") let prefsMenuItem = NSMenuItem(submenu: prefsSubmenu) prefsSubmenu.addItem(withTitle: "通用设置", action: #selector(openGeneralSettings), keyEquivalent: ",") mainMenu.addItem(prefsMenuItem) // 示例2:自定义帮助菜单 let helpSubmenu = NSMenu(title: "帮助") let helpMenuItem = NSMenuItem(submenu: helpSubmenu) helpSubmenu.addItem(withTitle: "使用手册", action: #selector(openUserGuide), keyEquivalent: "") mainMenu.addItem(helpMenuItem) } func applicationDidFinishLaunching(_ notification: Notification) { let _ = NSApplication.shared.windows.map { $0.tabbingMode = .disallowed } let mainWindow = NSApplication.shared.windows.first! mainWindow.backgroundColor = NSColor(red: 1, green: 1, blue: 1, alpha: 0.3) mainWindow.titlebarAppearsTransparent = true mainWindow.titleVisibility = .hidden mainWindow.backgroundColor = NSColor(red: 1, green: 1, blue: 1, alpha: 1) } // 菜单选项对应的响应方法,需用@objc标记 @objc private func openGeneralSettings() { // 替换为你自己的设置页打开逻辑 } @objc private func openUserGuide() { // 替换为你自己的帮助页打开逻辑 } } @main struct VeyBoardApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } }
补充说明
- 如果你需要保留原有系统菜单的常用能力(比如编辑菜单的复制、粘贴、全选),不需要完全删除默认内容,可以在清空主菜单后,单独把需要的子项从原有默认菜单中取出,挂载到你自定义的菜单下即可。
- 所有菜单选项绑定的 action 方法,必须确保能通过响应者链被找到,否则菜单选项会呈灰色不可点击状态。
- 自定义菜单的快捷键设置只需要在
addItem时传入对应的keyEquivalent字符串即可,系统会自动匹配修饰键的默认规则。
内容的提问来源于stack exchange,提问作者pistacchio
相关产品推荐
相关产品推荐

