使用 NSXPCConnection 时如何同步等待回复块
How to synchronously wait for reply block when using NSXPCConnection
我正在使用 NSXPCConnection,我的接口调用之一有一个回复块,如下所示:
- (void)addItem:(NSData *) withLabel:(NSString *) reply:(void (^)(NSInteger rc))reply;
我这样称呼它:
__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc)
{
status = rc;
}
];
我的理解是回复块 运行 是异步的,并且可能在方法 returns 之后。
我想同步测试 return 代码,最好的方法是什么?
为了进一步阐明上面的代码片段:proxy
对象是使用 remoteObjectProxy
方法从 NSXPCConnection
对象获得的远程对象。这是一个重要的细节,因为这会影响调用回复块的队列。
I want to test the return code synchronously, what's the best way to
do it?
您真的不希望它 运行 同步。这只会阻止 queue/thread,该阻止正在 运行 开启,通常会导致严重崩溃。
相反,在 status = rc;
行之后,调用可以处理已完成事实的东西。让方法 return,让队列或事件循环 运行,然后在 addItem:withLabel:
完成时执行所需的工作。
像这样:
__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc) {
status = rc;
// like this ...
[someObject processReturnedStatus];
}
];
这就是调度组的用途。
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)。
我建议使用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;
我刚刚发现了一个可能更好的方法:
创建远程对象时使用 synchronousRemoteObjectProxyWithErrorHandler
而不是 remoteObjectProxy
。
不需要信号量或组。
我正在使用 NSXPCConnection,我的接口调用之一有一个回复块,如下所示:
- (void)addItem:(NSData *) withLabel:(NSString *) reply:(void (^)(NSInteger rc))reply;
我这样称呼它:
__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc)
{
status = rc;
}
];
我的理解是回复块 运行 是异步的,并且可能在方法 returns 之后。
我想同步测试 return 代码,最好的方法是什么?
为了进一步阐明上面的代码片段:proxy
对象是使用 remoteObjectProxy
方法从 NSXPCConnection
对象获得的远程对象。这是一个重要的细节,因为这会影响调用回复块的队列。
I want to test the return code synchronously, what's the best way to do it?
您真的不希望它 运行 同步。这只会阻止 queue/thread,该阻止正在 运行 开启,通常会导致严重崩溃。
相反,在 status = rc;
行之后,调用可以处理已完成事实的东西。让方法 return,让队列或事件循环 运行,然后在 addItem:withLabel:
完成时执行所需的工作。
像这样:
__block NSInteger status;
[proxy addItem:data withLabel:@"label" reply:^(NSInteger rc) {
status = rc;
// like this ...
[someObject processReturnedStatus];
}
];
这就是调度组的用途。
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)。
我建议使用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;
我刚刚发现了一个可能更好的方法:
创建远程对象时使用 synchronousRemoteObjectProxyWithErrorHandler
而不是 remoteObjectProxy
。
不需要信号量或组。