【问题标题】:NSXPCConnection pass an object by proxyNSXPCConnection 通过代理传递对象
【发布时间】:2013-01-17 15:43:40
【问题描述】:

Daemons and Services Programming Guides 表示可以通过打开的 XPC 连接返回代理对象,甚至作为回复块参数。

通过代理传递对象

大多数时候,复制对象并将它们发送到连接的另一端是有意义的。然而,这并不总是可取的。特别是:

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

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

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

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

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

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

所以问题是:谁能给我一个清晰的教程,告诉我如何在 XPC 方法调用的块回复中返回一个对象作为代理?

【问题讨论】:

    标签: objective-c xpc nsxpcconnection


    【解决方案1】:

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

    • 在 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];
    
        }];
    
    }
    

    【讨论】:

    • 感谢您跟进您的问题!它为我节省了一些时间。
    猜你喜欢
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 2018-01-07
    • 2023-03-30
    • 2017-09-11
    • 2018-04-20
    • 1970-01-01
    相关资源
    最近更新 更多