如何在Objective-C中包装采用块的异步方法并将其同步 [英] How to wrap an asynchronous method that takes a block and turn it synchronous in Objective-C

查看:81
本文介绍了如何在Objective-C中包装采用块的异步方法并将其同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想包装一个如下所示的异步API:

I want to wrap an async API that look like this:

[someObject completeTaskWithCompletionHandler:^(NSString *result) {

}];

变成一个我可以这样调用的同步方法:

into a synchronous method that I can call like this:

NSString *result = [someObject completeTaskSynchronously];

我该怎么做?我做了一些文档阅读和互联网搜索,并尝试使用"dispatch_semaphore"来尝试实现该目标,如下所示:

How do I do this? I did some doc reading and internet search, and attempt to use "dispatch_semaphore" to do try to achieve it like so:

-(NSString *) completeTaskSynchronously {
   __block NSString *returnResult;
   self.semaphore = dispatch_semaphore_create(0);  
   [self completeTaskWithCompletionHandler:^(NSString *result) {
       resultResult = result;
       dispatch_semaphore_signal(self.semaphore);
   }];

   dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
   return resultResult;
}

但是这似乎不起作用,它基本上只是在dispatch_semaphore_wait处停止了.执行永远不会到达执行_signal的代码块内.任何人都有有关如何执行此操作的代码示例?我怀疑该块必须位于与主线程不同的其他线程上吗?另外,假设我无权访问async方法背后的源代码.

But this doesn't seem to work, it basically just halt at dispatch_semaphore_wait. Execution never reaches inside block that do the _signal. Anyone has code example on how to do this? I suspect that the block has to be on a different thread other the main thread? Also, assume I don't have access to the source code behind the async method.

推荐答案

dispatch_semaphore_wait阻止示例中的主队列.您可以将异步任务分派到其他队列:

dispatch_semaphore_wait blocks the main queue in your example. You can dispatch the async task to a different queue:

__block NSString *returnResult;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_async(queue,^{
     result = [someObject completeTaskSynchronously];
});

或使用其他系统,例如NSRunLoop:

Or use some other system, like NSRunLoop:

   __block finished = NO;
   [self completeTaskWithCompletionHandler:^(NSString *result) {
       resultResult = result;
       finished = YES;
   }];
    while (!finished) {
        // wait 1 second for the task to finish (you are wasting time waiting here)
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    }

这篇关于如何在Objective-C中包装采用块的异步方法并将其同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆