猫猫学iOS(五十一)多线程网络之GCD下载合并图片_队列组的使用

本文主要是介绍猫猫学iOS(五十一)多线程网络之GCD下载合并图片_队列组的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

猫猫分享,必须精品

原创文章,欢迎转载。转载请注明:翟乃玉的博客
地址: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下载合并图片_队列组的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1138349

相关文章

使用Python进行文件读写操作的基本方法

《使用Python进行文件读写操作的基本方法》今天的内容来介绍Python中进行文件读写操作的方法,这在学习Python时是必不可少的技术点,希望可以帮助到正在学习python的小伙伴,以下是Pyth... 目录一、文件读取:二、文件写入:三、文件追加:四、文件读写的二进制模式:五、使用 json 模块读写

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log

C#中图片如何自适应pictureBox大小

《C#中图片如何自适应pictureBox大小》文章描述了如何在C#中实现图片自适应pictureBox大小,并展示修改前后的效果,修改步骤包括两步,作者分享了个人经验,希望对大家有所帮助... 目录C#图片自适应pictureBox大小编程修改步骤总结C#图片自适应pictureBox大小上图中“z轴

Python如何使用seleniumwire接管Chrome查看控制台中参数

《Python如何使用seleniumwire接管Chrome查看控制台中参数》文章介绍了如何使用Python的seleniumwire库来接管Chrome浏览器,并通过控制台查看接口参数,本文给大家... 1、cmd打开控制台,启动谷歌并制定端口号,找不到文件的加环境变量chrome.exe --rem

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi

基于C#实现PDF文件合并工具

《基于C#实现PDF文件合并工具》这篇文章主要为大家详细介绍了如何基于C#实现一个简单的PDF文件合并工具,文中的示例代码简洁易懂,有需要的小伙伴可以跟随小编一起学习一下... 界面主要用于发票PDF文件的合并。经常出差要报销的很有用。代码using System;using System.Col

redis-cli命令行工具的使用小结

《redis-cli命令行工具的使用小结》redis-cli是Redis的命令行客户端,支持多种参数用于连接、操作和管理Redis数据库,本文给大家介绍redis-cli命令行工具的使用小结,感兴趣的... 目录基本连接参数基本连接方式连接远程服务器带密码连接操作与格式参数-r参数重复执行命令-i参数指定命