NSXPCConnection передает объект через прокси

В руководствах по программированию демонов и служб сообщается, что можно вернуть прокси-объект через открытое соединение XPC даже в качестве параметра блока ответа.

Передача объекта через прокси

В большинстве случаев имеет смысл копировать объекты и отправлять их на другую сторону соединения. Однако это не всегда желательно. Особенно:

Если вам нужно разделить один экземпляр данных между клиентским приложением и помощником, вы должны передать объекты через прокси. Если объекту необходимо вызывать методы других объектов в вашем приложении, которые вы не можете или не хотите передавать через соединение (например, объекты пользовательского интерфейса), вы должны передать объект через прокси — либо вызывающий, либо вызываемый (где возможно) или релейный объект, который вы создаете специально для этой цели. Недостатком передачи объектов через прокси является значительное снижение производительности (поскольку каждый доступ к объекту требует межпроцессного взаимодействия). По этой причине вам следует передавать объекты по доверенности только в том случае, если невозможно передать их путем копирования.

Вы можете настроить дополнительные прокси-объекты аналогично тому, как вы настроили свойство remoteObjectInterface исходного соединения. Сначала определите, какой параметр методу должен передаваться через прокси, затем укажите объект NSXPCInterface, определяющий интерфейс для этого объекта.

Возникают первые вопросы: как должен быть определен объект, который будет передаваться прокси? Как объект, соответствующий протоколу NSXPCProxyCreating? Должны ли быть реализованы методы remoteObjectProxy и remoteObjectProxyWithErrorHandler:?

Далее следует пример, который мне совершенно не ясен. В частности, я не понимаю, где я должен вызывать метод NSXPCInterface (setInterface:forSelector:argumentIndex:ofReply:) для внесения параметра в белый список в качестве прокси: в коде службы XPC или в хосте?

Первым параметром метода является параметр 0, за ним следует параметр 1 и так далее.

В этом случае для параметра ofReply передается значение НЕТ, поскольку этот код модифицирует белый список для одного из параметров самого метода. Если вы вносите класс в белый список для параметра блока ответа метода, вместо этого передайте YES.

Итак, вопрос: может ли кто-нибудь дать мне четкое руководство о том, как вернуть объект в качестве прокси в блочном ответе на вызов метода XPC?


person Andrea Cremaschi    schedule 02.02.2013    source источник


Ответы (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];

    }];

}
person Andrea Cremaschi    schedule 02.02.2013
comment
Спасибо за внимание к вашему вопросу! Это сэкономило мне время. - person Karim Agha; 25.02.2014