10

Daemons and Services Programming Guidesは、応答ブロック パラメーターとしても、開いている XPC 接続を介してプロキシ オブジェクトを返すことが可能であると述べています。

プロキシによるオブジェクトの受け渡し

ほとんどの場合、オブジェクトをコピーして接続の反対側に送信することは理にかなっています。ただし、これは常に望ましいとは限りません。特に:

クライアント アプリケーションとヘルパーの間でデータの 1 つのインスタンスを共有する必要がある場合は、オブジェクトをプロキシで渡す必要があります。オブジェクトがアプリケーション内の他のオブジェクトのメソッドを呼び出す必要があり、そのメソッドを接続を介して渡すことができない、または渡したくない場合 (ユーザー インターフェイス オブジェクトなど)、プロキシによってオブジェクトを渡す必要があります。可能)、またはその目的のために特別に作成したリレー オブジェクト。プロキシによるオブジェクトの受け渡しの欠点は、パフォーマンスが大幅に低下することです (オブジェクトへのすべてのアクセスでプロセス間通信が必要になるため)。このため、オブジェクトをコピーして渡すことができない場合にのみ、オブジェクトをプロキシで渡す必要があります。

初期接続の remoteObjectInterface プロパティを構成した方法と同様に、追加のプロキシ オブジェクトを構成できます。まず、プロキシによってメソッドに渡す必要があるパラメータを特定し、次にそのオブジェクトのインターフェイスを定義する NSXPCInterface オブジェクトを指定します。

最初の質問は、プロキシによって渡されるオブジェクトをどのように定義する必要があるかということです。NSXPCProxyCreatingプロトコルに準拠したオブジェクトとして? remoteObjectProxy と remoteObjectProxyWithErrorHandler: メソッドを実装する必要がありますか?

以下に例を示しますが、それは私にはまったくわかりません。特に、パラメーターをプロキシとしてホワイトリストに登録するには、NSXPCInterface メソッド (setInterface:forSelector:argumentIndex:ofReply:) をどこで呼び出す必要があるかわかりません: XPC サービス コードまたはホストで?

メソッドの最初のパラメーターはパラメーター 0 で、その後にパラメーター 1 が続きます。

この場合、このコードはメソッド自体のパラメーターの 1 つのホワイトリストを変更しているため、ofReply パラメーターに値 NO が渡されます。メソッドの応答ブロックのパラメーターのクラスをホワイトリストに登録する場合は、代わりに YES を渡します。

質問は、XPC メソッド呼び出しのブロック応答でオブジェクトをプロキシとして返す方法について、明確なチュートリアルを提供してくれる人はいますか?

4

1 に答える 1

15

XPC メソッド呼び出しのブロック応答でオブジェクトをプロキシとして返すには、 setInterface:forSelector:argumentIndex:ofReply: メソッドを両方とも呼び出す必要があります。

  • exportedInterfaceが宣言されている XPC サービスのエンドポイントで
  • 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];

    }];

}
于 2013-02-02T16:03:43.050 に答える