I can answer my own question now: to return an object as a proxy in a block reply of a XPC method call, one should call the setInterface:forSelector:argumentIndex:ofReply: method both:
- in the XPC service's endpoint, where the
exportedInterface
is declared - in the host, where the
remoteObjectInterface
is declared
I.e, common code:
// common (service/host) protocol definition
@protocol Service
@end
@protocol ServiceFactory
-(void)connectToNewService: (void (^)(id<Service>)reply;
@end
In the XPC Service:
// 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 code:
// 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];
}];
}