本文介绍了使用XPC与另一个应用程序进行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个窗口化应用程序,并且要添加一些功能,我需要另一个应用程序,该应用程序在登录时启动,并将数据同步到服务器(如果可用).

I have a windowed app, and to add some functionality I need another app which launches at login and sync data to server if available.

我曾尝试使用NSDistributionNotification,但它在沙盒应用程序中几乎没有用.我查了一下XPC并希望它能工作,但我只是不知道如何使它与助手一起工作.到目前为止,我已经使用XPC做到了这一点.

I have tried with NSDistributionNotification but its practically useless in a sandboxed app. I looked up XPC and hoped it will work but I just dont know how to get it to work with the helper. So far I have done this using XPC.

主应用

    NSXPCInterface *remoteInterface = [NSXPCInterface interfaceWithProtocol:@protocol(AddProtocol)];
    NSXPCConnection *xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.example.SampleService"];

    xpcConnection.remoteObjectInterface = remoteInterface;

    xpcConnection.interruptionHandler = ^{
        NSLog(@"Connection Terminated");
    };

    xpcConnection.invalidationHandler = ^{
        NSLog(@"Connection Invalidated");
    };

    [xpcConnection resume];

    NSInteger num1 = [_number1Input.stringValue integerValue];
    NSInteger num2 = [_number2Input.stringValue integerValue];

    [xpcConnection.remoteObjectProxy add:num1 to:num2 reply:^(NSInteger result) {
        NSLog(@"Result of %d + %d = %d", (int) num1, (int) num2, (int) result);
    }];

XPC服务

In main () ...
SampleListener *delegate = [[SampleListener alloc] init];
NSXPCListener *listener = [NSXPCListener serviceListener];
listener.delegate = delegate;
[listener resume];

// In delegate
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
    NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(AddProtocol)];
    newConnection.exportedInterface = interface;
    newConnection.exportedObject = [[SampleObject alloc] init];
    [newConnection resume];
    return YES;
}

// In Exported Object class

-(void)add:(NSInteger)num1 to:(NSInteger)num2 reply:(void (^)(NSInteger))respondBack {
    resultOfAddition = num1 + num2;
    respondBack(resultOfAddition);
}

这工作正常,现在我需要将此结果传递给Helper应用.我怎样才能做到这一点 ?如果XPC不能解决您的问题,那么我应该使用哪一个?有指针吗?

This works fine, now I need to pass this result to Helper app. How Can I do this ? If XPC is not the answer here to communicate, then which one should I be using ? Any pointers please ?

推荐答案

对于一直为此苦苦挣扎的人,我终于能够使用NSXPCConnection

Alright for anyone that has been struggling with this, I was finally able to 100% get communication working between two application processes, using NSXPCConnection

要注意的关键是您只能为三个对象创建一个NSXPCConnection.

The key to note is that you can only create an NSXPCConnection to three things.

  1. XPC服务.您可以严格通过以下方式连接到XPCService名称
  2. 马赫服务.您还可以连接到Mach服务严格通过名称
  3. 一个NSXPCEndpoint.这就是我们寻找,以在两个应用程序进程之间进行通信.
  1. An XPCService. You can connect to an XPCService strictly througha name
  2. A Mach Service. You can also connect to a Mach Servicestrictly through a name
  3. An NSXPCEndpoint. This is what we'relooking for, to communicate between two application processes.

问题在于我们不能直接将NSXPCEndpoint从一个应用程序转移到另一个应用程序.

The problem being that we can't directly transfer an NSXPCEndpoint from one application to another.

它涉及到创建一个包含以下内容的machservice启动代理(参见此示例). NSXPCEndpoint属性.一个应用程序可以连接到machservice,并将该属性设置为它自己的[NSXPCListener anonymousListener].endpoint

It involved creating a machservice Launch Agent (See this example for how to do that) that held an NSXPCEndpoint property. One application can connect to the machservice, and set that property to it's own [NSXPCListener anonymousListener].endpoint

然后另一个应用程序可以连接到machservice,并请求该端点.

Then the other application can connect to the machservice, and ask for that endpoint.

然后使用该端点创建一个NSXPCConnection,它成功地在两个应用程序之间建立了桥梁.我已经测试了来回发送对象,并且一切正常.

Then using that endpoint, an NSXPCConnection can be created, which successfully established a bridge between the two applications. I have tested sending objects back and forth, and it all works as expected.

请注意,如果您的应用程序是沙盒,您必须创建一个XPCService,作为您的应用程序和Machservice之间的中间人

Note that if your application is sandboxed, you will have to create an XPCService, as a middle man between your Application and the Machservice

我很高兴我能做到这一点-我在SO中相当活跃,因此,如果有人对源代码感兴趣,只需添加注释,我就可以努力发布更多详细信息

I'm pretty pumped that I got this working-- I'm fairly active in SO, so if anybody is interested in source code, just add a comment and I can go through the effort to post more details

我遇到的一些障碍:

您必须启动您的machservice,以下是这些行:

You have to launch your machservice, these are the lines:

   OSStatus                    err;
   AuthorizationExternalForm   extForm;

   err = AuthorizationCreate(NULL, NULL, 0, &self->_authRef);
   if (err == errAuthorizationSuccess) {
      NSLog(@"SUCCESS AUTHORIZING DAEMON");
   }
   assert(err == errAuthorizationSuccess);

   Boolean             success;
   CFErrorRef          error;

   success = SMJobBless(
                        kSMDomainSystemLaunchd,
                        CFSTR("DAEMON IDENTIFIER HERE"),
                        self->_authRef,
                        &error
                        );

此外,每次重建守护程序时,都必须使用以下bash命令卸载以前的启动代理:

Also, every time you rebuild your daemon, you have to unload the previous launch agent, with these bash commands:

sudo launchctl unload /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
sudo rm /Library/LaunchDaemons/com.example.apple-samplecode.EBAS.HelperTool.plist
sudo rm /Library/PrivilegedHelperTools/com.example.apple-samplecode.EBAS.HelperTool

(当然还有您的相应标识符)

(With your corresponding identifiers, of course)

这篇关于使用XPC与另一个应用程序进行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 03:09