GCD:异步等待条件

Tha*_*ham 1 asynchronous grand-central-dispatch ios

在我的iOS应用程序中,我想在更新UI之前等待条件成为现实.我这样做:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
  while (!condition) NSLog("waiting for the condition");
  dispatch_sync(dispatch_get_main_queue, ^{
    //update the UI here
  });
});
Run Code Online (Sandbox Code Playgroud)

上面的代码工作正常,但我想问一下使用while循环来做等待工作是好还是不好,如果有更好的方法.谢谢!

---更新

该条件实际上是4个BOOL变量的组合.每个变量都与来自服务器的内容请求相关联.我正在使用AFNetworking框架.在4个请求中的每个请求的完成块中,我将关联的BOOL变量设置为YES.所以,实际的while循环是这样的:

while (!([MyRequest request1].isFinished && [MyRequest request2].isFinished && [MyRequest request3].isFinished && [MyRequest request4].isFinished)) NSLog("waiting for the condition");
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 6

在修订后的问题中,您可能AFNetworking希望依赖四个操作.这要容易得多.您可能只需添加一个新操作,并使其依赖于其他四个操作:

NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // update UI
    }];
}];

[operation addDependency:requestOneOperation];
[operation addDependency:requestTwoOperation];
[operation addDependency:requestThreeOperation];
[operation addDependency:requestFourOperation];

[queue addOperation:operation];
Run Code Online (Sandbox Code Playgroud)

addDependency机制基本上isFinished为您执行其他四个操作中的每个操作的KVO .这是使用NSOperation像AFNetworking这样的基于框架的乐趣之一.这种依赖很容易做到.


原始答案:

如果你必须这样做,你可能会使用信号量,例如,你创建一个信号量:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
Run Code Online (Sandbox Code Playgroud)

你有异步块等待:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    dispatch_semaphore_wait(semaphore);
    dispatch_sync(dispatch_get_main_queue, ^{
        //update the UI here
    });
});
Run Code Online (Sandbox Code Playgroud)

并且当条件满足时,否则将设置此条件标志的代码将:

dispatch_semaphore_signal(semaphore);
Run Code Online (Sandbox Code Playgroud)

话虽如此,除非绝对必要,否则我宁愿看不到阻塞队列(甚至是并发全局队列).如果其他代码可以发出信号量信号,我不确定为什么它不能只是启动UI更新本身.如果我确实使用了这种信号量技术,至少我会在我自己创建的队列中进行这种等待过程,而不是全局队列.


您可以在许多情况下使用并且我可能更喜欢的另一种方法是使用键值观察:

例如,我可以观察到像这样someProperty调用的对象的属性的变化obj:

[obj addObserver:self forKeyPath:@"someProperty" options:NSKeyValueObservingOptionNew context:NULL];
Run Code Online (Sandbox Code Playgroud)

然后我会实现observeValueForKeyPath:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"someProperty"])
    {
        NSLog(@"update UI here");
    }
}
Run Code Online (Sandbox Code Playgroud)

每当someProperty我的obj对象的属性更新时,我的observeValueForKeyPath方法都会被调用.

仅供参考,我还要确保在此对象发布之前,我将删除观察者obj:

[obj removeObserver:self forKeyPath:@"someProperty"];
Run Code Online (Sandbox Code Playgroud)

显然,这假设someProperty符合键值编码的.但如果是的话,这是一项很棒的技巧.