在我的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个请求中的每个请求的完成块中,我将关联的BOOL变量设置为YES。 所以,实际的while循环是这样的:
while (!([MyRequest request1].isFinished && [MyRequest request2].isFinished && [MyRequest request3].isFinished && [MyRequest request4].isFinished)) NSLog("waiting for the condition");
答案 0 :(得分: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];
addDependency
机制基本上为您执行其他四个操作中isFinished
的KVO。这是使用基于NSOperation
的框架(如AFNetworking)的乐趣之一。这种依赖很容易做到。
原始答案:
如果你必须这样做,你可能会使用信号量,例如,你创建一个信号量:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
您的异步块等待:
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
属性时,都会调用observeValueForKeyPath
方法。
仅供参考,我还要确保在此对象发布之前,我将移除obj
的观察者:
[obj removeObserver:self forKeyPath:@"someProperty"];
显然,这假设someProperty
是Key Value Coding Compliant。但如果是的话,这是一项很棒的技术。
答案 1 :(得分:0)
虽然这里的一般模式是正确的(Apple将其称为“调用回调”),但while(!condition)
位也称为“自旋锁”,绝对不是等待a的最佳方式条件。请考虑改为使用NSTimer
或NSRunLoop
。