当我们需要在多个异步的任务完成之后去处理某些事情,如异步下载多张图片,等所有图片下载完成之后,再去做一些事情,那么怎样检测这些异步下载完所有图片的事件队列呢?可以用dispatch_group,她可以在添加到它里面的所有任务都完成之后同步(阻塞主线程)异步的通知,以便做接下来的事情
用dispatch_group_wait同步通知
一般的用法是: 在 某一个异步下载任务之前调用dispatch_group_enter(dispatch_group)进入diapatch_group
在改异步下载任务完成之后调用dispatch_group_leave(dispatch_group)来退出
以上重复的执行,直到所有的任务执行完毕
然后
dispatch_group_wait(dispatch_group, DISPATCH_TIME_FOREVER); // 5
这行代码之后的代码会在所有的任务完成之后执行,他有个返回值,如果超时会返回一个非零值
- (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1
__block NSError *error;
dispatch_group_t downloadGroup = dispatch_group_create(); // 2
for (NSInteger i = 0; i < 3; i++) {
NSURL *url;
switch (i) {
case 0:
url = [NSURL URLWithString:kOverlyAttachedGirlfriendURLString];
break;
case 1:
url = [NSURL URLWithString:kSuccessKidURLString];
break;
case 2:
url = [NSURL URLWithString:kLotsOfFacesURLString];
break;
default:
break;
}
dispatch_group_enter(downloadGroup); // 3
Photo *photo = [[Photo alloc] initwithURL:url
withCompletionBlock:^(UIImage *image, NSError *_error) {
if (_error) {
error = _error;
}
dispatch_group_leave(downloadGroup); // 4
}];
[[PhotoManager sharedManager] addPhoto:photo];
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
dispatch_async(dispatch_get_main_queue(), ^{ // 6
if (completionBlock) { // 7
completionBlock(error);
}
});
});
}
参考博文:http://ios.jobbole.com/81566/
第二种异步通知:用dispatch_group_notify,当dispatch_group中没有任何任务时就会调用该方法
用一下代码替换掉dispatch_group_wait()及之后的代码
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{ // 4
if (completionBlock) {
completionBlock(error);
}
});
上面在下载图片时迭代了三次,依次下载图片,这样效率不是很高,可以改进一下,让for循环并发的执行,dispatch_apply就是做这个的,他表现的像个for循环,但可以并发的迭代,并且是同步的,在所有的迭代完成以后才返回
网友评论