MacOS应用如何自定义App菜单中「设置...」(Cmd+,)的触发动作?
定位并修改MacOS应用的「设置」菜单项
方法1:通过Action和快捷键定位(最可靠)
系统默认的「设置」菜单项Action固定为showPreferences:,快捷键是Cmd+,——不管菜单标题因本地化如何变化,这两个标识始终稳定。可以通过递归遍历菜单栏,匹配属性来定位目标菜单项:
import AppKit func findPreferencesMenuItem() -> NSMenuItem? { guard let mainMenu = NSApp.mainMenu else { return nil } // 递归遍历所有菜单项 func searchMenuItems(in menu: NSMenu) -> NSMenuItem? { for item in menu.items { if item.action == Selector(("showPreferences:")) && item.keyEquivalent == "," && item.keyEquivalentModifierMask == .command { return item } if let submenu = item.submenu { if let foundItem = searchMenuItems(in: submenu) { return foundItem } } } return nil } return searchMenuItems(in: mainMenu) } // 使用示例 if let preferencesItem = findPreferencesMenuItem() { // 修改菜单项的Action为自定义方法 preferencesItem.action = #selector(YourViewController.customPreferencesAction(_:)) // 也可以直接替换整个菜单项 let newItem = NSMenuItem(title: "自定义设置...", action: #selector(YourViewController.customPreferencesAction(_:)), keyEquivalent: ",") newItem.keyEquivalentModifierMask = .command if let parentMenu = preferencesItem.parent { let index = parentMenu.items.firstIndex(of: preferencesItem)! parentMenu.replaceItem(at: index, with: newItem) } } // 自定义Action示例 @objc func customPreferencesAction(_ sender: Any?) { // 执行你的自定义设置逻辑 }
方法2:通过菜单标题定位(适合固定本地化场景)
如果你的应用只针对特定语言环境发布,可以直接匹配菜单标题(比如中文的「设置...」,英文的「Preferences...」):
func findPreferencesMenuItemByTitle() -> NSMenuItem? { guard let mainMenu = NSApp.mainMenu else { return nil } func searchMenuItems(in menu: NSMenu) -> NSMenuItem? { for item in menu.items { if item.title == "设置..." { // 中文环境,英文替换为"Preferences..." return item } if let submenu = item.submenu { if let foundItem = searchMenuItems(in: submenu) { return foundItem } } } return nil } return searchMenuItems(in: mainMenu) }
方法3:直接重新构建应用菜单(完全自定义)
如果需要彻底替换默认菜单结构,可以直接创建新的NSMenu并赋值给NSApp.mainMenu,其中包含自定义的设置菜单项:
func setupCustomMainMenu() { let mainMenu = NSMenu() // 应用菜单(比如「你的应用名」菜单) let appMenu = NSMenu(title: "") let preferencesItem = NSMenuItem(title: "设置...", action: #selector(YourViewController.customPreferencesAction(_:)), keyEquivalent: ",") preferencesItem.keyEquivalentModifierMask = .command appMenu.addItem(preferencesItem) // 添加其他默认菜单项(比如关于、退出等) appMenu.addItem(NSMenuItem.separator()) appMenu.addItem(NSMenuItem(title: "退出 \(Bundle.main.displayName!)", action: #selector(NSApp.terminate(_:)), keyEquivalent: "q")) mainMenu.addItem(NSMenuItem(title: Bundle.main.displayName!, submenu: appMenu)) // 添加其他菜单(比如文件、编辑等) NSApp.mainMenu = mainMenu }
注意:如果用SwiftUI开发,可以在App结构体中通过NSApplicationDelegateAdaptor实现上述逻辑,或者在@main类中重写applicationDidFinishLaunching方法执行定位修改操作。
内容的提问来源于stack exchange,提问作者Kaven
相关产品推荐
相关产品推荐

