Mac Catalyst中NSSharingService使用问题及插件类转换失败排查
解决Mac Catalyst中NSSharingService不可用及Bundle协议转换nil问题
我来帮你梳理下遇到的问题和对应的解决思路,先从你最初的困境说起:
一、为啥直接用NSSharingService会报错?
Mac Catalyst本质是把UIKit应用适配到macOS的框架,它默认屏蔽了AppKit的API,而NSSharingService是AppKit专属的类,所以你在Catalyst代码里直接引用就会触发'NSSharingService' is unavailable in Mac Catalyst的错误。你的这段代码确实没法直接运行:
#if targetEnvironment(macCatalyst) extension NSSharingService { //错误:'NSSharingService' is unavailable in Mac Catalyst class func shareContent ( content: [AnyObject], button: NSButton ) { let sharingServicePicker = NSSharingServicePicker (items: content ) sharingServicePicker.showRelativeToRect(button.bounds, ofView: button, preferredEdge: NSRectEdge.MaxY) } } #endif
二、嵌入macOS Bundle后协议转nil的原因
你尝试用嵌入macOS Bundle的方式绕开限制,但转协议时得到nil,大概率是这几个问题:
- 协议没做Objective-C兼容:跨Bundle的类型转换依赖Objective-C的动态特性,你的
ReaderTranslatorCommonInterfaces协议没加@objc修饰,Swift没法在不同Bundle间识别这个协议类型。 - Bundle配置或架构不匹配:要确保嵌入的Bundle是纯macOS平台编译的,且和主Catalyst应用的架构(arm64/x86_64)完全一致,否则加载后也没法正常实例化类。
- Principal Class的命名出错:Info.plist里的
principalClass必须是完整的类名(模块名+类名),如果拼写错了,就找不到对应的类。
要是想继续用Bundle方案,这么改就行:
- 给协议加上
@objc,让它支持跨Bundle的动态识别:@objc public protocol ReaderTranslatorCommonInterfaces { func test() -> String } - 给实现类也加上
@objc(你已经继承了NSObject,这步很重要):@objc open class ReaderTranslatorAppKit: NSObject, ReaderTranslatorCommonInterfaces { @objc public func test() -> String { "test 1" } } - 检查Info.plist的
principalClass值,确保和类的完全限定名一致,比如ReaderTranslatorAppKit.ReaderTranslatorAppKit。 - 确认Bundle的嵌入设置:在主应用的Build Phases里,把这个macOS Bundle加到
Embed Plug-Ins,并勾选Code Sign On Copy。
三、你最终的解决方案很靠谱
你提到的用独立macOS项目共享代码,再通过CFNotificationCenterGetDarwinNotifyCenter和UserDefaults(suiteName:)实现跨应用通信的方法,确实是绕开Catalyst AppKit限制的有效方案。独立macOS项目可以自由使用NSSharingService这类AppKit API,而Darwin通知和共享UserDefaults能很好地实现两个应用之间的数据传递,完美解决了你的需求。
内容的提问来源于stack exchange,提问作者Victor Kushnerov
相关产品推荐
相关产品推荐

