AJ学IOS(51)多线程网络之GCD下载合并图片_队列组的使用
AJ分享,必须精品
合并图片(图片水印)第一种方法
效果
实现:
思路:
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();
AJ学IOS(51)多线程网络之GCD下载合并图片_队列组的使用的更多相关文章
- AJ学IOS(44)之网易彩票自定义图片在右边的Button_弹出view_ios6,7简单适配
AJ分享,必须精品 效果: 注意图里面了吗,其实那个效果做起来真的很简单,在iOS中苹果给我们封装的很好,关键是那个按钮 系统的按钮的图片是在左边的,这里我们需要把他调整到右边,然后呢需要我们自己做一 ...
- AJ学IOS 之小知识之xcode6自动提示图片插件 KSImageNamed的安装
AJ分享,必须精品 一:首先看效果 KSImageNamed是让XCode能预览项目中图片的插件 很牛逼,据说写这个插件的牛人在日本~ 主要针对imageNamed:方法 效果如图: 安装: 首先需要 ...
- AJ学IOS(36)UI之手势事件旋转_缩放_拖拽
AJ分享,必须精品 效果 完成一个图片的捏合缩放,拖拽,旋转动作. 设计思路 拖拽: 首先是最简单的拖拽 //拖拽 -(void)panTest { UIPanGestureRecognizer *p ...
- AJ学IOS(18)UI之QQ聊天布局_键盘通知实现自动弹出隐藏_自动回复
AJ分享,必须精品 先看图片 第一步完成tableView和Cell的架子的图 完善图片 键盘弹出设置后图片: 自动回复图: 粗狂的架子 tableView和Cell的创建 首相tableView为了 ...
- AJ学IOS(07)UI之UITextField代理事件_类似QQ登陆窗口的简单实现
AJ分享,必须精品 先看效果图: 学习代码 // // NYViewController.m // 05-UITextField事件_UIKit复习 // // Created by apple on ...
- AJ学IOS(55)多线程网络之图片下载框架之SDWebImage
AJ分享,必须精品 效果: 代码: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsO ...
- AJ学IOS(48)多线程网络之多线程简单了解
AJ分享,必须精品 一:进程和线程 1:什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 比如同时打开QQ.Xcode,系统就会分 ...
- iOS开发多线程篇 08 —GCD的常见用法
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- iOS开发多线程篇 07 —GCD的基本使用
iOS开发多线程篇—GCD的基本使用 一.主队列介绍 主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行. 提示:如果把任务放到主队列中进 ...
随机推荐
- SQL Server2008执行脚本
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\osql.exe" -E -i C:\Users\zhiheng\Des ...
- 死磕Lambda表达式(四):常用的函数式接口
失去人性,失去很多:失去兽性,失去一切.--<三体> 在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口.它们主要 ...
- 物联网时代-新基建-ThingsBoard调试环境搭建
前言 2020开年之际,科比不幸离世.疫情当道.经济受到了严重的损失.人们都不幸的感慨: 2020年真是太不真实的一年,可以重新来过就好了!国家和政府出台了拯救经济和加速建设的利好消息.3月份最热的词 ...
- Journal of Proteome Research | Utilization of the Proteome Data Deposited in SRMAtlas for Validating the Existence of the Human Missing Proteins in GPM (解读人:梁嘉琪)
文献名:Utilization of the Proteome Data Deposited in SRMAtlas for Validating the Existence of the Human ...
- 关于Quartz .NET(V3.0.7)的简要说明
目录 0. 任务调度 1. Quartz .NET 1.1 基本概念 1.2 主要接口和对象 2. 使用示例 2.0 准备工作 2.1 每间隔一定时间间隔执行一次任务 2.3 某天的固定时间点执行任务 ...
- 使用burp插件captcha-killer识别图片验证码
0x01 开发背景 说起对存在验证码的登录表单进行爆破,大部分人都会想到PKav HTTP Fuzzer,这款工具在前些年确实给我们带来了不少便利.反观burp一直没有一个高度自定义通杀大部分图片验证 ...
- MS15-034漏洞复现、HTTP.SYS远程代码执行漏洞
#每次命令都百度去找命令,直接弄到博客方便些: 漏洞描述: 在2015年4月安全补丁日,微软发布的众多安全更新中,修复了HTTP.sys中一处允许远程执行代码漏洞,编号为:CVE-2015-1635( ...
- Android LinearLayout线性布局详解
为了更好地管理Android应用的用户界面里的各组件,Android提供了布局管理器.通过使用布局管理器,Android应用图形用户界面具有良好的平台无关性.推荐使用布局管理器来管理组件的分布.大小, ...
- Apache服务器故障排除攻略
Apache服务器故障排除攻略 应用服务器Apache浏览器配置管理网络应用 随着网络技术的普及.应用和Web技术的不断完善,Web服务已经成为互联网上重要的服务形式之一.原有的客户端/服务器模式正 ...
- coding++:TransactionDefinition 接口介绍
TransactionDefinition类结构: 作用: 1.TransactionDefinition接口被用于Spring事物支持的核心PlatformTransactionManager接口, ...