更改 macOS 上的默认命令菜单

问题描述 投票:0回答:4

我正在尝试更改 macOS SwiftUI 应用程序中的默认命令。我想将一些自定义命令附加到“查看”菜单,但我无法让它工作。

这是我尝试过的:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            AppView()
                .environmentObject(AppModel.shared)
                .environment(\.managedObjectContext, AppModel.shared.cloudKitCoordinator.coreDataStack.viewContext)
        }
        .commands {
            ViewCommands()
            SidebarCommands()
            ElementCommands()
            NavigationCommands()
        }
    }
}

struct ViewCommands: Commands {
    var body: some Commands {
        
        CommandMenu("View") {
            Button("Do something View related") {}
        }
    }
}

但它不是将命令附加到“查看”菜单,而是创建第二个同名菜单:

有没有人有幸更改了默认命令菜单,或者这只是 SwiftUI 的一部分,仍然有点原始?

swift macos swiftui
4个回答
9
投票

使用 CommandGroup,它具有用于追加或替换现有菜单的初始化选项:

.commands {
    CommandGroup(before: CommandGroupPlacement.newItem) {
        Button("before item") {
            print("before item")
        }
    }

    CommandGroup(replacing: CommandGroupPlacement.appInfo) {
        Button("Custom app info") {
            // show custom app info
        }
    }

    CommandGroup(after: CommandGroupPlacement.newItem) {
        Button("after item") {
            print("after item")
        }
    }
}

很好的教程:https://swiftwithmajid.com/2020/11/24/commands-in-swiftui/


6
投票

接受的答案在建议

CommandGroup
而不是
CommandMenu
方面总体上是正确的,并且有助于向我们指出 Swift with Majid (一个很棒的网站),但令人愤怒的是没有给我们确切的答案 - 哪个
 CommandGroupPlacement
用于 View 菜单?

为了避免所有其他人的尝试和错误,它是

CommandGroup(before: CommandGroupPlacement.toolbar) {
    Toggle("Show X", isOn: $model.settings.showX)
    Toggle("Show Y", isOn: $model.settings.showY)
    Divider()
}

0
投票
extension AppDelegate {
    func applicationWillUpdate(_ notification: Notification) {
        DispatchQueue.main.async {
            guard let currentMainMenu = NSApplication.shared.mainMenu else { return }

            // remove some items that cannot be deleted from SwiftUI
            ["Edit", "File", "Window"].forEach { name in
                currentMainMenu.item(withTitle: name).map { NSApp.mainMenu?.removeItem($0) }
            }
            
            guard let menu = currentMainMenu.item(withTitle: "View")?.submenu else { return }
            // remove sub-items of "View"
            menu.removeAllItems()
            
            //add new items
            menu.addItem(self.recentsPlusFavorites)
            menu.addItem(self.recentsMini)
            menu.addItem(self.recentsLarger)
        }
    }
}

0
投票

从 iOS 16.0、macOS 13.0 开始,Apple 引入了新的 API 来处理该问题。来自 SwiftUI 文档,代码示例:

    ///     @main
///     struct Example: App {
///         @Environment(\.openWindow) var openWindow
///
///         var body: some Scene {
///             ...
///
///             Window("Clipboard", id: "clipboard") {
///                 ClipboardContentView()
///             }
///             .commandsReplaced {
///                 CommandGroup(after: .pasteboard) {
///                     Section {
///                         Button("Show Clipboard") {
///                             openWindow(id: "clipboard")
///                         }
///                     }
///                 }
///             }
///         }
///     }

特定于查看菜单,基于Grimxn的答案,示例代码列表如下:

.commandsReplaced(content: {
        CommandGroup(before: .toolbar) {
            Section {
                Button {
                    print("new command")
                } label: {
                    Text("Full Screen")
                }

            }
        }
    })
© www.soinside.com 2019 - 2024. All rights reserved.