2

I'm using NSXPCConnection and one of my interface call has a reply block, like this:

- (void)addItem:(NSData *) withLabel:(NSString *) reply:(void (^)(NSInteger rc))reply;

Which I call like this:

__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc)
         {
             status = rc;
         }
];

My understanding is that the reply block run asynchronously, and potentially after the method returns.

I want to test the return code synchronously, what's the best way to do it?


To clarify further the snippet above: the proxy object is the remote object obtained from an NSXPCConnection object using the remoteObjectProxy method. This is an important detail as this impact on which queue the reply block is invoked.

4

4 に答える 4

4

これがディスパッチグループの目的です。

NSTimeInterval timeout = 120; // in seconds
__block NSInteger status;

dispatch_group_t syncGroup = dispatch_group_create();
dispatch_group_enter(syncGroup);

[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc)
    {
        status = rc;
        dispatch_group_leave(syncGroup);
    }
];

dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * timeout));

if(dispatch_group_wait(syncGroup, waitTime) != 0)
{
    // complain about a request timing out
}

// enjoy your status

プロキシを取得するために remoteObjectProxyWithErrorHandler を使用することを選択した場合は、エラー ハンドラに dispatch_group_leave(syncGroup) への呼び出しも忘れずに入れる必要があります。

于 2016-03-05T00:21:48.187 に答える
2

dispatch_semaphore を使用することを提案します。

// Create it before the block:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSInteger status = 0;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc) {
             status = rc;
             // In the block you signal the semaphore:
             dispatch_semaphore_signal(semaphore);
         }
];

// here wait for signal
// I dont remember exactly function prototype, but you should specify here semaphore and the time waiting (INFINITE)
dispatch_semaphore_wait(...);

// in non-ARC environment dont forget to release semaphore
dispatch_release(semaphore);

return status;
于 2016-03-06T13:52:40.047 に答える
2

戻りコードを同期的にテストしたいのですが、最善の方法は何ですか?

同期的に実行することは本当に望ましくありません。これは、ブロックが実行されているキュー/スレッドをブロックするだけで、通常は大混乱を引き起こします。

代わりに、status = rc;行の後に、それが完了したという事実を処理できる何かを呼び出します。メソッドが戻り、キューまたはイベント ループが実行され、必要な作業が完了するたびaddItem:withLabel:に実行されます。


このような:

__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc) {
             status = rc;
             // like this ...
             [someObject processReturnedStatus];
         }
];
于 2016-02-10T05:06:29.610 に答える