You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下Swift基于XPC实现IPC的极简客户端服务端开发方法

Swift XPC 简易IPC实现方案

前置说明

XPC通信要求服务端和客户端共享相同的通信协议定义,服务端需要注册一个全局唯一的Mach服务名用于客户端寻址。非沙盒命令行工具在同一用户下可直接使用,沙盒应用需要额外配置entitlements权限。

步骤1:定义公共通信协议

服务端和客户端都需要引入相同的协议定义:

import Foundation

@objc protocol XPCServiceProtocol {
    func sendMessage(_ message: String, reply: @escaping (String) -> Void)
}

步骤2:服务端实现(对应server_process.swift)

import Foundation

// 消息处理类,实现通信协议,对应你的on_message逻辑
class XPCServiceHandler: NSObject, XPCServiceProtocol {
    func sendMessage(_ message: String, reply: @escaping (String) -> Void) {
        print("服务端收到消息: \(message)")
        if message == "ping" {
            reply("pong")
        } else {
            reply("command not supported")
        }
    }
}

// 对应你的run_server_loop函数
func runServerLoop() {
    // 替换为你自定义的全局唯一Mach服务名,推荐使用反转域名格式
    let listener = NSXPCListener(machServiceName: "com.demo.xpc.server")
    listener.delegate = XPCListenerDelegate()
    listener.resume()
    // 启动运行循环保持进程不退出
    RunLoop.current.run()
}

// XPC连接监听代理
class XPCListenerDelegate: NSObject, NSXPCListenerDelegate {
    func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
        newConnection.exportedInterface = NSXPCInterface(with: XPCServiceProtocol.self)
        newConnection.exportedObject = XPCServiceHandler()
        newConnection.resume()
        return true
    }
}

// 启动服务
runServerLoop()

步骤3:客户端实现(对应client_process.swift)

import Foundation

// 对应你的some_way_to_connect函数
func connectToServer() -> NSXPCConnection? {
    // 和服务端使用完全相同的Mach服务名,普通用户服务无需加options参数
    let connection = NSXPCConnection(machServiceName: "com.demo.xpc.server")
    connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self)
    connection.resume()
    // 可选:配置连接中断回调
    connection.interruptionHandler = {
        print("与服务端连接中断")
    }
    return connection
}

// 建立连接
guard let clientConnection = connectToServer() else {
    fatalError("无法连接到服务端")
}

// 获取远程服务代理
guard let xpcService = clientConnection.remoteObjectProxyWithErrorHandler({ error in
    print("调用XPC服务出错: \(error)")
}) as? XPCServiceProtocol else {
    fatalError("获取远程服务代理失败")
}

// 对应你的client.send("ping")逻辑
xpcService.sendMessage("ping") { reply in
    print("客户端收到回复: \(reply)")
    // 收到回复后关闭连接
    clientConnection.invalidate()
    exit(0)
}

// 保持客户端运行等待异步回复
RunLoop.current.run(until: Date().addingTimeInterval(5))

运行注意事项

  • Mach服务名必须服务端和客户端完全一致,避免和系统或其他应用的服务名冲突
  • 沙盒应用需要在entitlements文件中添加com.apple.security.temporary-exception.mach-lookup.global-name权限,值为你定义的Mach服务名
  • 运行时先启动服务端进程,再启动客户端进程即可看到对应输出
  • 如果需要传输复杂自定义类型,需要提前在NSXPCInterface中声明对应类型的编码规则

内容的提问来源于stack exchange,提问作者Alok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 18:39:01