无法在 Mac 插件(Appkit + UIKit 之间的共享协议)中为 Mac Catalyst 应用程序加载 SwiftUI 视图

Unable to load SwiftUI view in MacPlugin(a shared protocol between Appkit + UIKit) for Mac Catalyst app

长话短说,我的用例是在 Mac 催化剂应用程序中包含状态栏菜单,为此我需要访问 Appkit 库。多亏了共享协议方法,我可以将 Appkit 和 UIkit 一起包含在催化剂应用程序中,只要它加载默认的 NSMenuItem,我就能够加载 NSStatubar,但是当我将自定义 SwiftUI 视图分配给 NSMenuItem 时,状态栏根本不显示.

这是我在 Appdelegate 中加载插件的代码

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    let macPlugin = AppKitContainer.loadPlugin()
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if let macPlugin = macPlugin {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                macPlugin.loadStatusMenu()
            }
        }
        return true
    }
}

这是我如何使用默认的 nsmenuitem

加载状态栏
class MacPlugin: NSObject, Plugin {
        
    var statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
    var menu = NSMenu()
        
    var contentMenuItemView = NSMenuItem.init()


    //load default nsmenuitem which works
    func loadStatusMenu() {
        statusBarItem.button?.title = "search"

        menu.addItem(NSMenuItem(title: "Quit Silicon Info", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"))

        statusBarItem.menu = menu
    }
}

输出 https://i.stack.imgur.com/v4pYO.png

这是我尝试在状态栏中加载 SwiftUI 视图的方式(基本上用 swiftui 视图替换了默认菜单项)

import AppKit

class MacPlugin: NSObject, Plugin {
        
    var statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
    var menu = NSMenu()
        
    var contentMenuItemView = NSMenuItem.init()
    
    //load swiftui in nsmenuitem doesn't work
    func loadStatusMenuWithSwiftUIView() {
        statusBarItem.button?.title = "search"

        let view = NSHostingView.init(rootView: Text.init("Hello world")) //SwiftUI view
        view.frame = NSRect(x: 0, y: 0, width: 292, height: 633)
        contentMenuItemView.view = view

        menu.addItem(contentMenuItemView)

        statusBarItem.menu = menu
        
    }
}

输出: 未显示状态栏

根据调试,方法没有被调用,与NSHostingView有关。 控制台没有错误。

感谢任何帮助。

这是不可能的。 IIRC 你的 AppKit 包只能访问你的主(Catalyst)应用程序加载的框架,其中包括 UIKit、AppKit 和 UIKit-compatible 版本的 SwiftUINSHostingViewAppKit-compatible 版本的 SwiftUI 中定义,它是一个单独的框架,并且 (AFAIK) 无法从您的 Catalyst 应用程序访问。

您可以创建一个单独的 Mac/AppKit 应用,然后将其与 Catalyst 应用捆绑在一起。即使 Catalyst 父应用程序不存在,此捆绑应用程序仍可以保留 运行,这是大多数状态栏应用程序的工作方式,因此可以说这是一个更好的解决方案。我写了一个blog post about how to do this, including a sample project.