在 iOS 开发中,使用 Grand Central Dispatch (GCD) 可以方便地处理异步任务并在所有任务完成后执行后续操作。要同步若干个异步调用,例如根据多个 URL 异步加载多张图片,并在所有图片加载完成后合成一张整图,我们可以使用 dispatch_group 来实现。
使用 dispatch_group 同步异步调用的步骤
- 创建 dispatch_group: 用于管理一组异步任务。
- 异步调用任务: 在每个异步任务(如图片下载)之前,使用 dispatch_group_enter 来标记进入组,下载完成后使用 dispatch_group_leave 来标记离开组。
- 等待所有任务完成: 使用 dispatch_group_notify 等待所有任务完成,并在所有任务完成后执行合并操作。
示例代码
以下是一个简单的示例代码,用于从多个 URL 异步下载图片并在所有图片下载完成后合成一张整图:
#import <UIKit/UIKit.h>
- (void)downloadImagesAndCombine {
NSArray<NSString *> *imageUrls = @[@"url1", @"url2", @"url3"]; // 替换为实际的图像URL
NSMutableArray<UIImage *> *images = [NSMutableArray arrayWithCapacity:imageUrls.count];
// 创建一个dispatch_group
dispatch_group_t group = dispatch_group_create();
for (NSString *urlString in imageUrls) {
// 将每个下载任务添加到dispatch_group中
dispatch_group_enter(group); // 进入group
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
if (image) {
@synchronized (images) {
[images addObject:image];
}
}
}
dispatch_group_leave(group); // 离开group
}];
[downloadTask resume];
}
// 当所有下载任务完成时执行合并操作
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self combineImages:images]; // 执行合并操作
});
}
- (void)combineImages:(NSArray<UIImage *> *)images {
// 在这里处理合成图像的代码
// 例如将多个图像合成一张整图
NSLog(@"All images downloaded and ready to combine.");
}
代码说明
创建 dispatch_group: dispatch_group_t group = dispatch_group_create(); 创建一个新的调度组。
异步下载图片: 遍历 URL 数组,针对每个 URL:
- 调用 dispatch_group_enter(group) 以标记进入组。
- 使用 NSURLSession 发起异步下载任务,在完成回调中处理下载逻辑。
- 下载完成后,如果成功下载,使用 @synchronized 捕捉对 images 数组的写操作,确保线程安全,然后调用 dispatch_group_leave(group) 表示当前任务完成。
合并操作: 使用 dispatch_group_notify 设置一个回调,当所有下载任务都完成时,它会在主线程中执行指定的合并操作。
通过使用 dispatch_group,你可以有效地管理一组异步操作,并在所有操作完成后进行后续操作(如合成整图)。这种方法简洁且有效,能够保证在多线程环境中的数据一致性。