標籤:下載 ios 多線程 網路 圖片
貓貓分享,必須精品
原創文章,歡迎轉載。轉載請註明:翟乃玉的部落格
地址:http://blog.csdn.net/u013357243?viewmode=contents
合并圖片(圖片浮水印)第一種方法效果
實現:
思路:
1.分別下載2張圖片:大圖片、LOGO
2.合并2張圖片
3.顯示到一個imageView身上
// 非同步下載 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 1.下載第1張 NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"]; NSData *data1 = [NSData dataWithContentsOfURL:url1]; UIImage *image1 = [UIImage imageWithData:data1]; // 2.下載第2張 NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"]; NSData *data2 = [NSData dataWithContentsOfURL:url2]; UIImage *image2 = [UIImage imageWithData:data2]; // 3.合并圖片 // 開啟一個位元影像上下文 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 * 0.5; CGFloat image2H = image2.size.height * 0.5; CGFloat image2Y = image1H - image2H; [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)]; // 得到上下文中的圖片 UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext(); // 結束上下文 UIGraphicsEndImageContext(); // 4.回到主線程顯示圖片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = fullImage; }); });
但是這樣雖然在非同步線程中完成的,不過,當下載完第一個圖的時候,第二個圖還沒下,在等待,我們想讓每一個圖都在一個單獨的非同步線程裡面下載,於是我們用第二種方法。
:第二種方法
首先定義兩個imageView
@property (weak, nonatomic) IBOutlet UIImageView *imageView;@property (nonatomic, strong) UIImage *image1;@property (nonatomic, strong) UIImage *image2;
然後實現這樣實現
// 非同步下載 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 1.下載第1張 NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"]; NSData *data1 = [NSData dataWithContentsOfURL:url1]; self.image1 = [UIImage imageWithData:data1]; [self bindImages]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 2.下載第2張 NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"]; NSData *data2 = [NSData dataWithContentsOfURL:url2]; self.image2 = [UIImage imageWithData:data2]; [self bindImages]; });
工作原理是開兩個非同步線程來分別下載兩個圖片,下載結束後都會調用
【self bindImages】方法,這時候我們在s 方法中設定回到主介面重新整理,不過首先要判斷兩張圖是否有資料,如下:
- (void)bindImages{ if (self.image1 == nil || self.image2 == nil) return; // 3.合并圖片 // 開啟一個位元影像上下文 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 * 0.5; CGFloat image2H = self.image2.size.height * 0.5; CGFloat image2Y = image1H - image2H; [self.image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)]; // 得到上下文中的圖片 UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext(); // 結束上下文 UIGraphicsEndImageContext(); // 4.回到主線程顯示圖片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = fullImage; });}
雖然我們通過我們自己的想法解決了問題,不過其實我們有更好的解決方案,那就是隊列組
第三種方法:隊列組完成什麼時候用隊列組呢?
首先:分別非同步執行2個耗時的操作
其次:等2個非同步作業都執行完畢後,再回到主線程執行操作
如果想要快速高效地實現上述需求,可以考慮用隊列組,用法如下:
// 1.建立隊列組dispatch_group_t group = dispatch_group_create();// 2.1第一個隊列組非同步dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 執行1個耗時的非同步作業});// 2.2第二個隊列組非同步dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 執行1個耗時的非同步作業});// 3.所有隊列組非同步線程結束後dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的非同步作業都執行完畢後,回到主線程...});
那就讓我們來用隊列組完成他吧,代碼如下:
// 1.隊列組 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, ^{ NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"]; NSData *data1 = [NSData dataWithContentsOfURL:url1]; image1 = [UIImage imageWithData:data1]; }); // 3.下載圖片2 __block UIImage *image2 = nil; dispatch_group_async(group, queue, ^{ NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"]; NSData *data2 = [NSData dataWithContentsOfURL:url2]; image2 = [UIImage imageWithData:data2]; }); // 4.合并圖片 (保證執行完組裡面的所有任務之後,再執行notify函數裡面的block) dispatch_group_notify(group, queue, ^{ // 開啟一個位元影像上下文 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 * 0.5; CGFloat image2H = image2.size.height * 0.5; CGFloat image2Y = image1H - image2H; [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)]; // 得到上下文中的圖片 UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext(); // 結束上下文 UIGraphicsEndImageContext(); // 5.回到主線程顯示圖片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = fullImage; }); });
__block關鍵字
注意:這裡我們用到了一個__block的關鍵字,這是因為如果不加的話,block裡面的是不能訪問block外面的東西的。
小小總結:開啟非同步
(直接敲dispatch_a。。。就能出來一堆提示,然後選選填填,沒啥難度,前面說過了)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ code});
開啟隊列組:
首先建一個隊列組:
dispatch_group_t group = dispatch_group_create();
然後把原來放隊列的地方換成隊列組 並且用dispatch_get_global_queue這個
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 執行1個耗時的非同步作業});
上面這段能多弄幾個,弄幾個就有幾個線程
然後結束時候用這個:
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的非同步作業都執行完畢後,回到主線程...});
合并圖片的過程
步驟:
1.開啟一個位元影像上下文
2.1繪製第1張圖片
2.2繪製第2張圖片
3.得到上下文中的圖片
4.結束上下文
// 1.開啟一個位元影像上下文 UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0); // 2.1繪製第1張圖片 CGFloat image1W = image1.size.width; CGFloat image1H = image1.size.height; [image1 drawInRect:CGRectMake(0, 0, image1W, image1H)]; // 2.2繪製第2張圖片 CGFloat image2W = image2.size.width * 0.5; CGFloat image2H = image2.size.height * 0.5; CGFloat image2Y = image1H - image2H; [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)]; // 3.得到上下文中的圖片 UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext(); // 4.結束上下文 UIGraphicsEndImageContext();
貓貓學iOS(五十一)多線程網路之GCD下載合并圖片_隊列組的使用