多图片多线程异步下载


开发中非常常用的就是就是图片下载,我们常用的就是SDWebImage,但是作为开发人员,不仅要能会用,还要知道其原理。本文就会介绍多图下载的实现。

本文中的示例Demno地址,下载后项目位于iOS_Demo/09-多图片多线程下载

1 - 问题

开篇我就先将多图下载过程中出现的问题摆出来,让我们能够一一克服

1:下载过程要放到子线程中,否则会导致UI线程卡顿

2:图片会重复下载,我们不仅要把下载完的图片放到内存中,还要把下载队列也缓存起来,否则可能图片没有下载完,会多次创建下载队列

3:沙盒缓存,放到哪里,根据下面对沙盒文件的介绍我们需要把图片放到Library/Caches目录下。

Document : iTunes会备份
Library :
1:Caches:缓存文件,不会清除
2:Preferences:偏好设置,保存账号信息
tmp :临时路径,随时会被删除,临时的不是重要的数据

下载流程图

明白了问题后,我们需要制定战略(画流程图),这样根据流程图,下载过程就更为清晰明了。

根据流程图一些坑,我们就可以完美的避免掉了。这样写程序也更有章法。

2 - 开始下载图片

根据前面的介绍,我们需要有两个缓存对象:

  1. 图片data的内存缓存
  2. 下载队列的缓存

我们可以使用NSMutableDictionary进行缓存,

这里我们假设两个缓存对象分别是:

/** 内存中图片的缓存字典 */
@property (nonatomic,strong)NSMutableDictionary * memoryImages; /** 下载操作的字典 */
@property (nonatomic,strong)NSMutableDictionary * operations;

2.1 内存缓存中取值

所以下载前,我们先要到内存中取值

   NSData *imageData = [self.memoryImages objectForKey:url];

如果imageData对象存在,我们就直接设置到Cell上。

2.2 内存缓存中没有,我们到沙盒中取值

内存缓存中不存在时我们到沙盒中进行查看:

        NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
//获取图片名字,图片名称不能包含URL,
NSString *fileName = [url lastPathComponent];
NSString *filePaPath = [path stringByAppendingPathComponent:fileName]; //内存中没有图片的缓存 -- 从沙盒中取出
NSData *imageData = [NSData dataWithContentsOfFile:filePaPath];

如果图片存在,我们需要把图片设置到Cell上,并且放一份到内存缓存中

//沙盒中取出后,放一份到内存缓存中
[self.memoryImages setObject:imageData forKey:url];

这样下次就不用频繁访问沙盒了。

2.2 内存缓存中没有,沙盒中也没有,我们需要判断下载队列是否已经存在

如果网速慢一些,并且Cell上下滑动的频率快一些的话,假如第一次第5行的Cell显示的时候,内存缓存中没有,沙盒中也没有,这时我们创建了下载对象,然后这行Cell被滑出屏幕,再次进来的时候图片还是没有下载完毕,经过判断内存缓存中没有,沙盒中也没有,我们如果再次创建下载对象的话,就会重复下载图片了,所以我们要把下载队列也进行缓存,当内存缓存中没有,沙盒中也没有时,我们先判断下载队列中是否已经存在了。

这里使用的是NSBlockOperation

NSBlockOperation *doo = [self.operations objectForKey:url];

2.2 内存缓存中没有,沙盒中也没有,下载队列也没有

这时我们就需要创建下载对象进行下载了。

首先我们先可以设置一个占位图,这样的显示更为友好一下。

 NSBlockOperation *downO = [NSBlockOperation blockOperationWithBlock:^{
NSURL *uurl = [NSURL URLWithString:url]; NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *down = [session dataTaskWithURL:uurl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//图片的下载过程 }]; [down resume];
}];

同时加入下载队列

  //下载对象加入队列中
[self.operations setObject:downO forKey:url];
[self.queue addOperation:downO];

图片下载完毕后,我们需要

//把图片data存入内存中
[self.memoryImages setObject:data forKey:url]; //同时写入沙盒中,永久缓存
[data writeToFile:filePaPath atomically:YES];

同时在主线程中更新UI

 [[NSOperationQueue mainQueue] addOperationWithBlock:^{

 UIImage *image = [UIImage imageWithData:data];
cell.iconView.image = image;
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];

这样完整的图片下载过程就好了。

【iOS系列】-多图片多线程异步下载的更多相关文章

  1. iOS开发网络篇—多线程断点下载

    iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...

  2. IOS GCD图片数据异步下载,下载完成后合成显示

    关于GCD使用详解,请看我的上一篇blog:http://www.cnblogs.com/xin-lang/p/6278606.html 前段时间遇到个需要异步下载,下载完成后再组合显示的东西.这里我 ...

  3. 使用webClient实现图片同步,异步下载

    WebClient.DownloadFile 方法 将具有指定 URI 的资源下载到本地文件. 命名空间:System.Net 程序集:System(在 system.dll 中) 同步实现参考代码: ...

  4. iOS tableView的图片缓存异步载入

    1.建立一个viewController. .h文件实现UIScrollViewDelegate和UITableViewDelegate,并声明ICTableViewDelegate(用来实现图片有缓 ...

  5. iOS开发网络篇—大文件的多线程断点下载

    http://www.cnblogs.com/wendingding/p/3947550.html iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时 ...

  6. iOS开发网络篇—大文件的多线程断点下载(转)

    http://www.cnblogs.com/wendingding/p/3947550.html   iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了 ...

  7. [原]unity3d之http多线程异步资源下载

    郑重声明:转载请注明出处 U_探索 本文诞生于乐元素面试过程,被面试官问到AssetBundle多线程异步下载时,愣了半天,同样也被深深的鄙视一回(做了3年多u3d 这个都没用过),所以发誓要实现出来 ...

  8. 使用开源库 SDWebImage 异步下载缓存图片(持续更新)

    source  https://github.com/rs/SDWebImage APIdoc  http://hackemist.com/SDWebImage/doc Asynchronous im ...

  9. [Xcode 实际操作]八、网络与多线程-(22)使用GCD多线程技术异步下载图片

    目录:[Swift]Xcode实际操作 本文将演示如何使用使用GCD多线程技术异步下载图片. Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法 ...

随机推荐

  1. 3月题外:关于GeoServer和OpenLayers3实用开源插件或组件的总结

    Geoserver篇 注意: 1)用法 GeoServer-Extension的使用方法:将jar包直接放入部署在tomcat上的geoserver/WEB-INF/lib文件夹中 2)在安装插件时, ...

  2. python打印表格式数据,留出正确的空格和段落星号或注释

    python打印表格式数据,留出正确的空格,格式化打出 代码如下: def printPicnic(itemsDict,leftWidth,rightWidth): print('PICNIC ITE ...

  3. python服务器环境搭建(1)——本地服务器准备

    去年十月底到新公司上班,由于公司旧系统存在各种问题同时不便于扩展,而公司领导对17年寄予很大的期望,用户量.收入要上一个新台阶,我经过全面评估后,决定全部用python重构过,开发一个基于微服务架构的 ...

  4. 3389: [Usaco2004 Dec]Cleaning Shifts安排值班

    3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 102  Solved: ...

  5. 解决Gerrit的git unpack error问题和error Missing unknown ec867cebfd2be97c3603c45fac03c75dcf68d0ca

    参考链接:http://www.cnblogs.com/yuxc/p/3508964.html 解决方法: 由于帖子里面用的是mysql数据库,而我用的是h2数据库,还特意自己去找了H2数据库的进入方 ...

  6. Archlinux中卸载 Slim

    Slim 是图形登录器.最近停止更新了,据说在systemd中有兼容性问题. 卸载Slim的原因是某计算机使用的是AMD显卡的Catalyst驱动,图形驱动一旦出问题,Slim就无法启动,给维护造成困 ...

  7. 在LaTeX 与 LyX 中设置“Contents”为“目录”

    在 LaTeX 中,目录一般被显示为英文"Contents",因此需要设置成"目录". 通常在 Preamble 按照如下方式设置: \renewcommand ...

  8. QT 中使用 c++ 的指针

    之前没有接触过 c++,不过听说 c++ 的指针很坑,直到最近在用 QT / C++ 写一个 Linux Deepin 系统上检测网络流量和网速的小程序时,发现 c++ 的指针用起来真的特别蛋疼. 不 ...

  9. 使用Nginx+CppCMS构建高效Web应用服务器

    使用Nginx+CppCMS构建高效Web应用服务器 1:Why当前,越来越多的网站使用了各种框架,大部分框架使用了脚本语言.半编译语言等.比如Java.Python.Php.C#.NET等.这些框架 ...

  10. Octave Tutorial(《Machine Learning》)之第一课《数据表示和存储》

    Octave Tutorial 第一课 Computation&Operation 数据表示和存储 1.简单的四则运算,布尔运算,赋值运算(a && b,a || b,xor( ...