一:简介
XPC
是 macOS
里苹果官方比较推荐和安全的的进程间通信机制。
集成流程简单,但是比较绕。
-
主要需要集成
XPC Server
这个模块,这个模块最终会被apple
的根进程launchd
管理和以独立进程的方法唤起和关闭, 我们主app 进程并不需要管理这个进程的生命周期。 -
特点:主要做权限分离和错误隔离使用,使用独立进程的方法,可以避免独立进程
crash
影响到主进程, 而且独立进程可以和主进程赋予不同的权限,比如是否沙盒,是否有网络权限等。 -
find /System/Library/Frameworks -name \*.xpc
命令可以查看系统使用的xpc服务。 -
下面一张官方图,说明了对应的关系。
UI App
作为client
端,只要去监听对应的XPC 服务,launchd
就会拉起对应的XPC Server
XPC Server
作为 服务端,提供xpc服务,并接受client的消息。
两者之间通过protocol
的方式进行互相调用,解耦。
- 下面创建的app的数据流向
二:创建流程
- 创建主进程UI app
- 配置ui app的名字为 XpcApp.
- 按照步骤给 app 以添加target 的方式添加xpc 模块。
- 创建Xpc server 的名字为:
XpcServer
,
api 选择OC 接口的api,而不是C接口的版本
最后一项内嵌到UI APP中,最终运行打包后,会在XpcApp.app/Contents/XPCServices/XpcServer.xpc
路径里面找到它。
- 最终的项目架构如下,
XpcApp 包含两个文件夹,分别为 UI和xpcserver的文件夹,
对应两个target。
三:demo 运行
- 由于XpcServer里面官方已经给了demo 足够运行的代码,我们可以不用添加任何代码就可以运行。
我们在XpcServer.m
里面添加个 log 作为调试输出就行。
这里只加了一句log输出,会在server 收到 ui app 传递来的消息的时候打印,并将收到的两个数字相加后返回。
// This implements the example protocol. Replace the body of this class with the implementation of this service's protocol.
- (void)performCalculationWithNumber:(NSNumber *)firstNumber andNumber:(NSNumber *)secondNumber withReply:(void (^)(NSNumber *))reply {NSInteger result = firstNumber.integerValue + secondNumber.integerValue;NSLog(@"server 收到 UI Clicent App的两个数字: %@, %@", firstNumber, secondNumber);reply(@(result));
}
- 配置UI App 文件。
这里的代码调用方法可以参考XCode自动生成的XpcServerProtocol.h
文件里面的注释,里面说明了怎么在Client 端发送消息。
ViewController.m
中,替换成如下代码:
#import "ViewController.h"
#import "XpcServerProtocol.h"
#import "XpcServer.h"@interface ViewController ()
@property (nonatomic, strong) NSXPCConnection *xpcConnect;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.xpcConnect = [[NSXPCConnection alloc] initWithServiceName:@"com.jimbo.xpc.XpcServer"];NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(XpcServerProtocol)];self.xpcConnect.remoteObjectInterface = interface;[self.xpcConnect resume];
}- (IBAction)sendMsgClick:(id)sender {NSLog(@"ui app 发送数字 231, 119");[[self.xpcConnect remoteObjectProxy] performCalculationWithNumber:@231 andNumber:@119 withReply:^(NSNumber *reply) {// We have received a response.NSLog(@"ui 收到了 xpc server 返回的数字: %@", reply);}];
}- (void)dealloc {[self.xpcConnect invalidate];
}@end
- 在storyboard 中添加个button,绑定到上面的
- (IBAction)sendMsgClick:(id)sender
方法中。 - 运行
点击button 后,关注 app的控制台
xpc server 的控制台
两个进程都有打印消息,说明通讯成功。
四:备注
- demo中传递消息用的protocol里面的方法
(performCalculationWithNumber: andNumber: withReply:)
只是官方默认提供的,根据实际需要也可以添加其他方法,比如传递字符串,json等。 - 自己的xpc server 是内嵌到 app 包里的,默认只能有自己的app包的主程序进行调用,如果需要让其他app 进行通信调用,需要创建
launchd.plist
然后拷贝到系统路径下的.../LaunchDaemons
文件夹。
具体可以参考man launchd.plist
- 两个进程都可以互相主动发消息的,只是demo没有添加对应的代码。