猫猫学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实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

C#中Guid类使用小结

《C#中Guid类使用小结》本文主要介绍了C#中Guid类用于生成和操作128位的唯一标识符,用于数据库主键及分布式系统,支持通过NewGuid、Parse等方法生成,感兴趣的可以了解一下... 目录前言一、什么是 Guid二、生成 Guid1. 使用 Guid.NewGuid() 方法2. 从字符串创建

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注