在SwiftUI环境中自定义应用程序的主菜单

4ioopgfo  于 2022-11-21  发布在  Swift
关注(0)|答案(2)|浏览(123)

我正在创建一个NSViewRepresentable视图,以在SwiftUI代码中使用NSView。我需要NSViewRepresentable代码通过NSApp.mainMenu属性自定义应用的主菜单。
但结果是,任务的合格AppKit代码在SwiftUI环境中不起作用。通过调试主菜单,我看到我添加到菜单中的项目出现在NSMenu示例中,但这些项目没有显示在SwiftUI应用程序菜单中,但它们显示在AppKit应用程序菜单中。
调试显示,在SwiftUI环境中,应用程序的主菜单使用SwiftUI.AppKitMainMenuItem对象,而不是NSMenuItem。但它是苹果的私有类,我不能使用。
如何在SwiftUI环境中实现这一点?我真的需要在我的NSViewRepresentable类中使用可可代码库来完成这一点,因为我正在为AppKit、UIKit和SwiftUI开发一个通用扩展。

5uzkadbs

5uzkadbs1#

SwiftUI macOS主菜单

  • Xcode 14.0以上版本,macOS蒙特里12.5.1*

要从主菜单中删除所有五个默认菜单项,请使用以下方法:

import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {
            
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        
        let menus = ["File","Edit","View","Window","Help"]
        
        menus.forEach { menu in
            NSApp.mainMenu?.item(withTitle: menu).map {
                NSApp.mainMenu?.removeItem($0)
            }
        }
    }
}

然后将@NSApplicationDelegateAdaptor属性 Package 放入SwiftUI @main应用程序的结构中。若要生成自定义菜单项,请使用.commands {...}修饰符。

@main struct YourApp: App {
    
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {

        WindowGroup {
            ContentView()
        }
        .commands {
            CommandMenu("Custom") {
                Button("Add Item", action: { } )
                    .keyboardShortcut("N")
                Divider()
                Button("Edit Item", action: { } )
                    .keyboardShortcut("E")
            }
        }
    }
}

或者,您可以将@NSApplicationDelegateAdaptor属性 Package 器放在ContentView结构中,而不是放在YourApp@main结构中。

@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
yqhsw0fo

yqhsw0fo2#

我也调查过这个问题--这可能是swiftUI上的一个bug,它一直在破坏菜单。
总之--看看这条线:SwiftUI Update the mainMenu [SOLVED] kludgey
将它放在AppDelegate.applicationWillUpdate函数的DispatchQueue.main.async闭包中

import Foundation
import AppKit

public class AppDelegate: NSObject, NSApplicationDelegate {
    public func applicationWillUpdate(_ notification: Notification) {
        DispatchQueue.main.async {
            let currentMainMenu = NSApplication.shared.mainMenu

            //
            // Do your menu stuff here
            //
            // The below removes the Edit menu
            //

            let editMenu: NSMenuItem? = currentMainMenu?.item(withTitle: "Edit")
            if nil != editMenu {
                NSApp.mainMenu?.removeItem(editMenu!)
            }
        }
    }
}

相关问题