macOS沙箱Swift应用父子应用跨进程通信实现方案咨询
解决方案
优先方案:CFMessagePort 正确配置与Swift实现
前置配置(解决签名/权限报错问题)
- 父子应用均开启App Sandbox能力,父应用勾选「Outgoing Connections (Client)」权限,子应用勾选「Incoming Connections (Server)」权限
- 父子应用加入同一个App Group,组名格式必须为
{你的开发者TeamID}.{自定义组名},TeamID可在苹果开发者账号详情页查看 - 关闭Xcode的「Automatically manage signing」选项,手动选择在苹果开发者后台生成的、已绑定当前App Group的provision profile,即可解决profile显示
None required无法修改的问题
多实例适配逻辑
父应用启动每个子应用实例时,通过启动参数为其分配唯一的端口标识,避免多个子实例端口冲突。
Swift代码实现
子应用(服务端)代码
import CoreFoundation class ChildPortServer { private var localPort: CFMessagePort? // 启动时传入带App Group前缀的唯一端口名 func start(portName: String) { let callback: CFMessagePortCallBack = { _, _, data, _ in guard let cfData = data, let received = Data(referencing: cfData) as? Data else { return nil } // 收到父应用消息后处理,可发通知给UI层更新 DispatchQueue.main.async { NotificationCenter.default.post(name: NSNotification.Name("ParentMessageReceived"), object: received) } // 可选返回响应数据给父应用 let response = "子应用已收到消息".data(using: .utf8)! return Unmanaged.passRetained(response as CFData) } var context = CFMessagePortContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) var freeInfo: DarwinBoolean = false guard let port = CFMessagePortCreateLocal(nil, portName as CFString, callback, &context, &freeInfo) else { print("端口创建失败,请检查配置") return } localPort = port let runloopSource = CFMessagePortCreateRunLoopSource(nil, port, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, .commonModes) } }
父应用(客户端)代码
func sendMessageToChild(portName: String, content: Data) -> Data? { guard let remotePort = CFMessagePortCreateRemote(nil, portName as CFString) else { print("子应用端口连接失败") return nil } var returnData: Unmanaged<CFData>? let status = CFMessagePortSendRequest( remotePort, 0, content as CFData, 3, 3, CFRunLoopMode.defaultMode.rawValue, &returnData ) guard status == kCFMessagePortSuccess, let cfResult = returnData?.takeRetainedValue() else { return nil } return Data(referencing: cfResult) }
备选方案
NSXPCConnection
你之前对XPC的认知存在偏差:NSXPCConnection完全支持有UI的独立进程通信,没有只能用于无界面后台服务的限制,原生Swift支持更友好,不需要手动处理CoreFoundation类型的内存管理,调试成本更低。
App Group共享目录中转
如果不需要实时通信,也可以用App Group共享目录作为中转:父应用为每个子实例生成独立的消息文件写入共享目录,子应用启动时读取对应文件,也可以通过NSFilePresenter监听文件变化实现消息推送,适合大内容传输场景。
内容的提问来源于stack exchange,提问作者Xiao Xiao
相关产品推荐
相关产品推荐

