開(kāi)發(fā)中,如果我們需要同時(shí)開(kāi)啟多條線程下載數(shù)據(jù),并且等待這多條線程執(zhí)行完畢,即數(shù)據(jù)下載完成后,再來(lái)對(duì)這多個(gè)數(shù)據(jù)進(jìn)行操作。這樣的需求在項(xiàng)目開(kāi)發(fā)中還是比較常見(jiàn)的,那么有什么比較好的方法可以實(shí)現(xiàn)這樣的需求呢?答案是:隊(duì)列組。
下面就針對(duì)這個(gè)問(wèn)題分別展開(kāi)研究。
1、異步下載兩種圖片,分別合并之后再回到主線程刷新UI
/// 異步下載兩種圖片,分別合并之后再回到主線程刷新UI
- (void)mergedImages1 {
// 異步下載
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 1.下載第1張
UIImage *image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl1]]];
// 2.下載第2張
UIImage *image2 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl2]]];
// 3.合并圖片
// 開(kāi)啟一個(gè)位圖上下文
UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
// 繪制第1張圖片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 繪制第2張圖片
CGFloat image2W = image2.size.width;
CGFloat image2H = image2.size.height * 0.5;
CGFloat image2Y = image1H * 0.5;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的圖片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束上下文
UIGraphicsEndImageContext();
// 4.回到主線程顯示圖片
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = fullImage;
});
});
}
2、分別開(kāi)啟兩條線程下載圖片,然后再判斷圖片是否下載成功,最后合并完圖片之后回到住線程刷新UI
/// 分別開(kāi)啟兩條線程下載圖片,然后再判斷圖片是否下載成功,最后合并完圖片之后回到住線程刷新UI
- (void)mergedImages2 {
// 異步下載
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 1.下載第1張
UIImage *image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl3]]];
self.image1 = image1;
[self bindImages];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 2.下載第2張
UIImage *image2 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl4]]];
self.image2 = image2;
[self bindImages];
});
}
- (void)bindImages {
if (self.image1 == nil || self.image2 == nil) return;
// 3.合并圖片
// 開(kāi)啟一個(gè)位圖上下文
UIGraphicsBeginImageContextWithOptions(self.image1.size, NO, 0.0);
// 繪制第1張圖片
CGFloat image1W = self.image1.size.width;
CGFloat image1H = self.image1.size.height;
[self.image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 繪制第2張圖片
CGFloat image2W = self.image2.size.width;
CGFloat image2H = self.image2.size.height * 0.5;
CGFloat image2Y = image1H * 0.5;
[self.image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的圖片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束上下文
UIGraphicsEndImageContext();
// 4.回到主線程顯示圖片
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = fullImage;
});
}
3、利用隊(duì)列組方式,輕松實(shí)現(xiàn)
/// 利用隊(duì)列組方式,輕松實(shí)現(xiàn)
- (void)queueGroupImplementation {
// 1.隊(duì)列組
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.下載圖片1
__block UIImage *image1 = nil;
dispatch_group_async(group, queue, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl5]]];
image1 = image;
});
// 3.下載圖片2
__block UIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImgUrl6]]];
image2 = image;
});
// 4.合并圖片 (保證執(zhí)行完組里面的所有任務(wù)之后,再執(zhí)行notify函數(shù)里面的block)
dispatch_group_notify(group, queue, ^{
// 開(kāi)啟一個(gè)位圖上下文
UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
// 繪制第1張圖片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 繪制第2張圖片
CGFloat image2W = image2.size.width;
CGFloat image2H = image2.size.height * 0.5;
CGFloat image2Y = image1H * 0.5;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的圖片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束上下文
UIGraphicsEndImageContext();
// 5.回到主線程顯示圖片
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = fullImage;
});
});
}
最終實(shí)現(xiàn)的UI顯示如下圖:

Simulator Screen Shot - iPhone 11 Pro Max - 2020-04-30 at 13.52.39.png
這里是主要的實(shí)現(xiàn)邏輯部分代碼,具體步驟請(qǐng)各位朋友下載demo自行查閱!