NSXPCConnection通过代理传递对象

时间:2013-02-02 11:23:55

标签: objective-c xpc nsxpcconnection

Daemons and Services Programming Guides表示可以通过打开的XPC连接返回代理对象,即使是作为回复块参数也是如此。

通过代理传递对象

  

大多数情况下,复制对象并将它们发送到连接的另一端是有意义的。但是,这并不总是令人满意的。特别是:

     

如果需要在客户端应用程序和帮助程序之间共享单个数据实例,则必须通过代理传递对象。   如果一个对象需要在你的应用程序中调用你不能或不希望通过连接的其他对象的方法(例如用户界面对象),那么你必须通过代理传递一个对象 - 调用者,被调用者(其中)可能),或您专门为此目的构建的中继对象。   通过代理传递对象的缺点是性能显着降低(因为对对象的每次访问都需要进程间通信)。因此,如果无法通过复制传递对象,则只应通过代理传递对象。

     

您可以配置其他代理对象,类似于配置初始连接的remoteObjectInterface属性的方式。首先,确定应该通过代理传递方法的哪个参数,然后指定一个NSXPCInterface对象,该对象定义该对象的接口。

第一个问题:如何定义代理传递的对象?作为符合NSXPCProxyCreating协议的对象?应该实现remoteObjectProxy和remoteObjectProxyWithErrorHandler:方法吗?

以下是一个例子,对我来说根本不清楚。特别是我不明白我应该在哪里调用NSXPCInterface方法(setInterface:forSelector:argumentIndex:ofReply :)将参数作为代理列入白名单:在XPC服务代码中还是在主机中?

  

方法的第一个参数是参数0,后跟参数1,依此类推。

     

在这种情况下,为ofReply参数传递值NO,因为此代码正在修改方法本身的一个参数的白名单。如果要为方法的回复块的参数将类列入白名单,请改为传递YES。

所以问题是:在XPC方法调用的块响应中,是否可以向我提供有关如何将对象作为代理返回的明确教程?

1 个答案:

答案 0 :(得分:9)

我现在可以回答我自己的问题:要在XPC方法调用的块回复中返回一个对象作为代理,应该调用setInterface:forSelector:argumentIndex:ofReply:method both:

  • 在XPC服务的端点中,exportedInterface被声明为
  • 在主机中,声明remoteObjectInterface

即,常用代码:

// common (service/host) protocol definition
@protocol Service
@end

@protocol ServiceFactory
-(void)connectToNewService: (void (^)(id<Service>)reply;
@end

在XPC服务中:

// Implement the one method in the NSXPCListenerDelegate protocol.
-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection*)newConnection {   

    NSXPCInterface *serviceFactoryInterface =[NSXPCInterface interfaceWithProtocol:@protocol(ServiceFactory)];
    NSXPCInterface *serviceInterface =[NSXPCInterface interfaceWithProtocol:@protocol(Service)];

    // connection has to be returned as proxy, not as a copy
    [serviceFactoryInterface setInterface: serviceInterface
                          forSelector: @selector(connectToNewService:)
                        argumentIndex: 0
                              ofReply: YES];

    newConnection.exportedInterface = serviceFactoryInterface;
    newConnection.exportedObject = self;

    [newConnection resume];
    return YES;

}

在主持人代码中:

// in the host

- (void)openNewService
{
    NSXPCConnection *xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"eu.mycompany.servicefactory"];
    NSXPCInterface *serviceFactoryInterface =[NSXPCInterface interfaceWithProtocol:@protocol(ServiceFactory)];
    NSXPCInterface *serviceInterface =[NSXPCInterface interfaceWithProtocol:@protocol(Service)];

    // connection has to be returned as proxy, not as a copy
    [serviceFactoryInterface setInterface: serviceInterface
                          forSelector: @selector(connectToNewService:)
                        argumentIndex: 0
                          ofReply: YES];

    xpcConnection.remoteObjectInterface = serviceFactoryInterface;
    [xpcConnection resume];

    [[xpcConnection remoteObjectProxy] connectToNewService:^(id<Service> newService) {

        // here a newService is returned as NSXPCDistantObject <Service>*
        [xpcConnection invalidate];

    }];

}