跨进程通信 macOS XPC 创建实例

一:简介

XPCmacOS 里苹果官方比较推荐和安全的的进程间通信机制。

集成流程简单,但是比较绕。

  • 主要需要集成 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的数据流向

二:创建流程

  1. 创建主进程UI app
  2. 配置ui app的名字为 XpcApp.
  3. 按照步骤给 app 以添加target 的方式添加xpc 模块。
  4. 创建Xpc server 的名字为: XpcServer,
    api 选择OC 接口的api,而不是C接口的版本
    最后一项内嵌到UI APP中,最终运行打包后,会在XpcApp.app/Contents/XPCServices/XpcServer.xpc路径里面找到它。
  5. 最终的项目架构如下,
    XpcApp 包含两个文件夹,分别为 UI和xpcserver的文件夹,
    对应两个target。

三:demo 运行

  1. 由于XpcServer里面官方已经给了demo 足够运行的代码,我们可以不用添加任何代码就可以运行。
    我们在XpcServer.m 里面添加个 log 作为调试输出就行。
    这里只加了一句log输出,会在server 收到 ui app 传递来的消息的时候打印,并将收到的两个数字相加后返回。
objectivec 复制代码
// 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));
}
  1. 配置UI App 文件。
    这里的代码调用方法可以参考XCode自动生成的XpcServerProtocol.h文件里面的注释,里面说明了怎么在Client 端发送消息。
    ViewController.m 中,替换成如下代码:
objectivec 复制代码
#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
  1. 在storyboard 中添加个button,绑定到上面的 - (IBAction)sendMsgClick:(id)sender方法中。
  2. 运行
    点击button 后,关注 app的控制台

    xpc server 的控制台

    两个进程都有打印消息,说明通讯成功。

四:备注

  1. demo中传递消息用的protocol里面的方法(performCalculationWithNumber: andNumber: withReply:)只是官方默认提供的,根据实际需要也可以添加其他方法,比如传递字符串,json等。
  2. 自己的xpc server 是内嵌到 app 包里的,默认只能有自己的app包的主程序进行调用,如果需要让其他app 进行通信调用,需要创建 launchd.plist 然后拷贝到系统路径下的.../LaunchDaemons文件夹。
    具体可以参考 man launchd.plist
  3. 两个进程都可以互相主动发消息的,只是demo没有添加对应的代码。
相关推荐
HerayChen10 分钟前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
hairenjing112313 分钟前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
小李飞刀李寻欢3 小时前
Mac电脑如何解压rar压缩包
macos·rar·解压
Java小白笔记3 小时前
Mac中禁用系统更新
macos
AndyFrank3 小时前
mac crontab 不能使用问题简记
linux·运维·macos
Mac新人3 小时前
一招解决Mac没有剪切板历史记录的问题
macos·mac
王拴柱3 小时前
Mac保护电池健康,延长电池使用寿命的好方法
macos·mac
daa203 小时前
macos中安装和设置ninja
macos
Java小白笔记4 小时前
Mac解决 zsh: command not found: ll
macos
小钱c75 小时前
Mac下安装Apache JMeter并启动
jmeter·macos·apache