在目标c中的同步调用中包装异步api

时间:2013-10-29 11:21:45

标签: ios iphone objective-c asynchronous

我有一个基本上调用Web服务的for循环。响应在完成处理程序

中处理

除非对所有请求都有响应,否则我不希望执行从此for循环中出来。

下面是我的代码段

for(ClassX objectX in myAraay)
{
     __block BOOL blockExecutionOver = NO ;
   // call web service with completion handeler
    callwebservice:^handler
   {
     // block execution
       blockExecutionOver = YES ;
   }

];

while (blockExecutionOver == NO)
    {
        [[NSRunLoop currentRunLoop] run];
    }
}
//do something here after above for loop is executed

我如何实现这一点。目前,这个运行循环对我没有任何意义。我对这些请求没有超时。因此我没有使用runtillDate或runMode

2 个答案:

答案 0 :(得分:1)

您可以使用NSCondition来实现这种行为。 E.g:

self.condition = [[NSCondition alloc] init];
[self.condition lock];

self.requestCount = 0;
for (...) {
   ...
   self.requestCount++;
   ...
}

if (self.requestCount > 0)
    [self.condition wait];
[self.condition unlock];

然后在你的完成块中你会这样做:

... process response ...
self.requestCount--;
if (self.requestCount == 0)
    [self.condition signal];

上述代码的作用是:

  1. 对于每个请求,计数器会递增,以便您知道有多少请求待处理;
  2. 发送所有请求后,等待信号量,这样你的线程就会停止;
  3. 当响应进来时,你处理它并递减计数器;
  4. 当计数器变为0时,你发送一个信号灯信号,什么会使原来的线程恢复。
  5. 顺便说一下,应该在与你停止等待信号量的线程不同的线程上调用完成处理程序。正如您可能会发现的那样,使用信号量并不像人们希望的那样直截了当,并且有很多捕获量。

    还可以采用其他方式,即使用NSOperationQueue,但这需要对代码进行更多重构。 Here你可以找到一个如何做到这一点的例子。

答案 1 :(得分:0)

所以你要锁定它,直到调用完成:

dispatch_queue_t q = dispatch_queue_create("com.my.queue", NULL);

dispatch_sync(q, ^{ 
    // Do your work here.
});