无法在 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 版本的 SwiftUI。 NSHostingView
在 AppKit-compatible 版本的 SwiftUI 中定义,它是一个单独的框架,并且 (AFAIK) 无法从您的 Catalyst 应用程序访问。
您可以创建一个单独的 Mac/AppKit 应用,然后将其与 Catalyst 应用捆绑在一起。即使 Catalyst 父应用程序不存在,此捆绑应用程序仍可以保留 运行,这是大多数状态栏应用程序的工作方式,因此可以说这是一个更好的解决方案。我写了一个blog post about how to do this, including a sample project.
长话短说,我的用例是在 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 版本的 SwiftUI。 NSHostingView
在 AppKit-compatible 版本的 SwiftUI 中定义,它是一个单独的框架,并且 (AFAIK) 无法从您的 Catalyst 应用程序访问。
您可以创建一个单独的 Mac/AppKit 应用,然后将其与 Catalyst 应用捆绑在一起。即使 Catalyst 父应用程序不存在,此捆绑应用程序仍可以保留 运行,这是大多数状态栏应用程序的工作方式,因此可以说这是一个更好的解决方案。我写了一个blog post about how to do this, including a sample project.