我正在执行一系列dispatch_async,我只想在完成后更新UI。问题是dispatch_async中的方法在一个单独的线程中调用某些内容,因此它在数据完全加载之前返回,并且在加载所有内容之前调用dispatch_group_notify。
所以我引入了一个无限循环让它等到设置了一个标志。 这是最好的方法吗?请参阅下面的代码。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();
for (...) {
dispatch_group_async(group, queue, ^{
__block BOOL dataLoaded = NO;
[thirdPartyCodeCallWithCompletion:^{
dataLoaded = YES;
}];
// prevent infinite loop
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
queue, ^{
dataLoaded = YES;
});
// infinite loop to wait until data is loaded
while (1) {
if (dataLoaded) break;
}
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//update UI
});
}
答案 0 :(得分:9)
您已经了解调度组。为什么不使用dispatch_group_wait()
,其中包括对超时的支持?您可以使用dispatch_group_enter()
和dispatch_group_leave()
而不是dispatch_group_async()
来完成群组,直到完成第三方通话的内部阻止完成为止。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();
for (...) {
dispatch_group_enter(group);
dispatch_async(queue, ^{
[thirdPartyCodeCallWithCompletion:^{
dispatch_group_leave(group);
}];
}
}
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSECS_PER_SEC));
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
使用dispatch_group_wait()
会使此代码同步,如果在主线程上运行则会很糟糕。根据超时情况应该发生的情况,您可以使用dispatch_group_notify()
并使用dispatch_after()
来更新UI,而不是试图假装块已完成。
更新:我调整了我的代码,以确保在主队列上发生“更新UI”,以防这个代码不在主线程上。
顺便说一句,我只使用dispatch_async()
作为调用thirdPartyCodeCallWithCompletion:
的块,因为原来使用了dispatch_group_async()
而我不确定假设方法是否是异步的。但是,大多数采用完成块的API都是异步的。如果是那个,那么你可以直接调用它。
答案 1 :(得分:5)
另一种方法是使用semaphore和dispatch_semaphore_wait:
// Create your semaphore, 0 is specifying the initial pool size
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@autoreleasepool {
// Your code goes here
}
// Release the resource and signal the semaphore
dispatch_semaphore_signal(semaphore);
});
// Wait for the above block execution, AKA Waits for (decrements) a semaphore.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// After this line you can now safely assert anything you want regarding the async operation since it is done.