如何使用私有API在原生AppKit应用中嵌入Mac Catalyst组件?
在原生AppKit应用中嵌入Mac Catalyst UIKit组件(私有API方案)
核心逻辑
Mac Catalyst本质是UIKit在macOS上的兼容运行层,我们可以借助私有API把UIKit控制器(比如TOCropViewController、MessageKit的会话控制器)包装进AppKit的视图层级里,实现反向嵌入——毕竟你已有庞大的AppKit代码库,没必要重构为Catalyst应用。
具体步骤
1. 项目基础配置
- 给AppKit项目添加
UIKit框架(Build Phases → Link Binary With Libraries里搜UIKit添加上)。 - 关闭Xcode的App Store相关验证:Scheme → Run → Arguments → Environment Variables加
OS_ACTIVITY_MODE=disable,同时Build Settings里把Enable App Store Connect API设为NO,避免私有API触发报错。
2. 准备AppKit容器视图
在要嵌入组件的NSViewController/NSWindow里,先加个NSView当容器:
let catalystContainer = NSView(frame: .init(x: 0, y: 0, width: 400, height: 400)) view.addSubview(catalystContainer) // 绑自动布局约束 catalystContainer.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ catalystContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor), catalystContainer.centerYAnchor.constraint(equalTo: view.centerYAnchor), catalystContainer.widthAnchor.constraint(equalToConstant: 400), catalystContainer.heightAnchor.constraint(equalToConstant: 400) ])
3. 用私有API嵌入UIKit控制器
通过私有类_UIWindowHostingView把UIKit控制器包装成能在AppKit里显示的视图:
import UIKit // 声明私有类的协议(绕过编译检查) @objc protocol _UIWindowHostingViewProtocol { init(rootViewController: UIViewController) var rootViewController: UIViewController? { get set } } class _UIWindowHostingView: UIView, _UIWindowHostingViewProtocol { @objc dynamic init(rootViewController: UIViewController) { super.init(frame: .zero) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // 实例化目标UIKit控制器,比如TOCropViewController let targetVC = TOCropViewController(image: UIImage(named: "test-img")!) // 创建Catalyst宿主视图 let hostingView = _UIWindowHostingView(rootViewController: targetVC) // 转成NSView加到容器里 if let nsHostingView = hostingView as? NSView { nsHostingView.frame = catalystContainer.bounds nsHostingView.autoresizingMask = [.width, .height] catalystContainer.addSubview(nsHostingView) }
4. 生命周期与交互适配
- UIKit控制器的生命周期方法会通过私有宿主视图自动同步AppKit的生命周期,不用额外处理。
- 常规交互(点击、手势)Catalyst兼容层会自动转译,复杂自定义交互需要确保UIKit响应链正常,比如不要在AppKit视图上拦截事件。
注意事项
- 系统更新风险:私有API没有官方保障,macOS大版本更新可能导致失效,每次更新后要测试兼容性。
- 视图操作规范:所有UI修改都要通过UIKit控制器来做,别直接动Catalyst宿主视图的层级,避免布局混乱。
- 性能优化:复杂组件(比如MessageKit)可能有轻微性能损耗,可以给UIKit视图开启光栅化:
targetVC.view.layer.shouldRasterize = true,同时设置rasterizationScale = UIScreen.main.scale。
特定组件适配提示
- TOCropViewController:只要传入的UIImage正常,裁剪完成的闭包能正常接收回调,基本不用额外适配。
- MessageKit:正常配置数据源和代理即可,它本身支持Catalyst,嵌入后聊天界面、输入框等功能都能正常工作。
内容的提问来源于stack exchange,提问作者eoirqgfoqkrognoqwfr
相关产品推荐
相关产品推荐

