ios - GCD : asynchronously wait for condition

标签 ios asynchronous grand-central-dispatch

在我的 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
  });
});

上面的代码工作得很好,但我想问一下使用while循环来做等待工作是否好,是否有更好的方法。
谢谢!

- -更新

条件实际上是 4 个 BOOL 变量的组合。每个变量都与来自服务器的内容请求相关联。我正在使用 AFNetworking 框架。在 4 个请求的每一个的完成 block 中,我将关联的 BOOL 变量设置为 YES。
所以,实际的while循环是这样的:
while (!([MyRequest request1].isFinished && [MyRequest request2].isFinished && [MyRequest request3].isFinished && [MyRequest request4].isFinished)) NSLog("waiting for the condition");

最佳答案

在修改后的问题中,听起来你有四个 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];

addDependency 机制本质上是 isFinished 的 KVO为您提供的其他四个操作中的每一个。这是使用 NSOperation 的乐趣之一。 AFNetworking 等基于框架的框架。这种依赖真的很容易做到。

原答案:

如果你必须这样做,你可能会使用一个信号量,例如,你会创建一个信号量:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

你会让你的异步 block 等待:
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
    });
});

当条件满足时,原本设置此条件标志的代码将改为:
dispatch_semaphore_signal(semaphore);

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

您可以在许多情况下使用并且我可能更喜欢的另一种方法是使用 key value observing :

例如,我可以观察到它们的变化 someProperty名为 obj 的对象的属性像这样:
[obj addObserver:self forKeyPath:@"someProperty" options:NSKeyValueObservingOptionNew context:NULL];

然后我会执行 observeValueForKeyPath :
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"someProperty"])
    {
        NSLog(@"update UI here");
    }
}

每当someProperty我的 obj 的属性(property)对象已更新,我的 observeValueForKeyPath方法将被调用。

仅供引用,我还要确保在此对象被释放之前,我会删除 obj 的观察者:
[obj removeObserver:self forKeyPath:@"someProperty"];

显然,这假设 somePropertyKey Value Coding Compliant .但如果是这样,这是一项很棒的技术。

关于ios - GCD : asynchronously wait for condition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19194009/

相关文章:

ios - UITableView里面UITableViewCell高度问题

objective-c - iOS 上 PDF 文档的默认纸张大小和单位

JavaScript 代理在 "get"上返回异步值

objective-c-blocks - 如何使用 dispatch_queue_set_specific() 和 dispatch_get_specific()

ios - SpriteKit,把一个进程放在另一个核心上?

cocoa - Cocoa 中的并发网络客户端

ios - 获取的结果 Controller 不会在运行时更新表

javascript - 通过if条件防止双击事件

c# - 在键盘事件中使用 CancellationToken 调用 Task.Delay 时出现 TaskCanceledException

asp.net-mvc - MVC4 "Cannot await"