You need to enable JavaScript to run this app. SwiftUI中如何移除、替换、添加菜单(XCode12.4/MacOS11.1含AppDelegate的Mac应用)
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 08:15:08