XPC 是 macOS 里经常用到的进程间通信机制。本文不关注 XPC 的内部机制,而是一篇教你如何上手 XPC 的文章。
创建
macOS
工程FRTestXPC
,选择Cocoa App Template
。在工程
FRTestXPC
里点击增加Target
,在弹出框搜索XPC
, 选择搜索结果中的XPC Service
,然后命名Target
为FRTestXPC_Helper
并将target
对应的 info.plist 文件中bundle id
修改为 'com.frank.xpchelper'选择
FRTestXPC Target
->Build Phases
然后新增CopyFiles
项目,将刚刚的FRTestXPC_Helper.xpc
加进去,注意Destination
必须要选择XPC Services
。否则后续主程序和 XPC 会无法建立连接。回过头来看工程目录里
FRTestXPC_Helper
->main.m
文件,这里main
函数是XPC
程序的入口函数。可以看到Xcode
已经帮助生成很多 demo code。我们已经不需要做太多。在主程序的窗口里增加一个 button,在点击方法里实现如下代码
NSXPCConnection *con = [[NSXPCConnection alloc] initWithServiceName:@"com.frank.xpchelper"]; NSXPCInterface *remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(FRTestXPC_HelperProtocol)]; con.remoteObjectInterface = remoteInterface; [[con remoteObjectProxy] upperCaseString:@"hello" withReply:^(NSString *reply) { NSLog(@"reply = %@",reply); }]; [con resume];
启动程序,点击 button,观察终端输出为 HELLO
# 一些说明
- Tips :作为 demo 可以删除掉
Project
里的各种Test Target
和 Test 文件,保持工程清爽直观。 - 我用的是
Xcode9.1
版本,创建好的 XPC 中的代码完全为 Xcode 自动生成的,(void)upperCaseString:(NSString *)aString withReply:(void (^)(NSString *))reply;
这个协议也是 Xcode 生成的,所以看上面代码不要太突兀,你自己试试就知道了。 - 初始化主程序
NSXPCConnection
的时候必须写正确 XPC 的service name.
# 一些 QA
Q: 什么场景下会用到 XPC? 具体到项目中说一下。 A: 我觉得用到 XPC 的地方主要还是希望让别的进程分担自己的任务,同时又能够及时的和主进程进行通信。(比如一些网络处理的服务)
Apple WWDC 的讲解也是这么说的 So if you just have some background piece of work that needs to happen every so often, you can use XPC to talk to it, initiate it, and get it running.
其次是考虑一些其他因素,比如
- 增加程序稳定性(XPC Service crash 但主程序不 crash).
- XPC 服务处理一些不够安全的东西,这时候我们不提供 XPC 任何权限,比如网络访问,文件访问等,但是主程序还是保留所有的权限。 相当于让小弟干活儿,但是不给小弟太多权利,干的了就干,干不了就别干…..
- 很重要一点:是这是 App Store 允许的多进程的方式。
Q: XPC 服务有界面吗? A: 一般都是后台进程。没见过有人用 XPC 搭建界面的。
Q: 系统是怎么通过以下这些 API 方法找到 XPC 服务的 ?
NSXPCInterface *myCookieInterface = [NSXPCInterfaceinterfaceWithProtocol:@protocol(XPC_HelperProtocol)];
NSXPCConnection *myConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.frank.xpchelper"];
A: 当 app 启动的时候,系统自动注册 app 中可见的 XPC 服务,当 app 与某个 XPC 服务建立连接,然后向他发送包含事件服务的消息。
When the app is launched, the system automatically registers each XPC service it finds into the namespace visible to the app. An app establishes a connection with one of its XPC services and sends it messages containing events that the service then handles
# 一个 Demo
以上的 demo 是最简单的,一般 XPC 用来做后台下载处理比较合适,所以写了一个比上面代码复杂一点点(不过还是很简单)的 demo 放到 github 上,这个 demo 是 XPC 双向同步的。即 XPC Service
可以不依赖于代理方法的回调而是直接给 Client app
发送消息。
NSXPCConnection
是最主要的 API,其余的 API 比如 NSXPCInterface
,都是依附于 Connection
。构建双向通信的 XPC Demo 在 ClientApp
和 XPC 里有一些代码非常相似。即互相暴露接口,互相暴露交接的对象。Demo 也提供了一些非常实用的构建 XPC 时用的 API。
Demo 地址: https://github.com/fanxiushan/Demo.XPCTestDemo
# 参考地址
Creating XPC Services (opens new window) Mac Technology Overview -> Kernel and Device Drivers Layer -> High-Level Features -> XPC Interprocess Communication and Services (opens new window) WWDC (opens new window) XPC (opens new window)