iOS多线程-05-多图下载
效果图
常见问题及解决方法
- 图片重复下载
- 将内存保存在内存或沙盒中。
- 若下载的图片量较大,则会出现UI界面不流畅的现象
- 在子线程中执行下载操作,然后回到主线程成中进行UI界面的刷新。
- 由于cell的循环利用造成的图片显示错乱问题
- 指定刷新表格的indexPath行。
- subTitle类型的cell,无法显示图片
- subtitle类型的cell中的imageView只有在第一次返回cell时设置图片,否则图片将不能显示(刷新表格也不行)。可以通过设置占位图片的方式来解决此问题。
思维导图
具体实现
其核心代码主要在tableView的返回创建cell的代理方法中,所以以下主要对该方法的实现进行解析
主要流程
设置模型类,包含以下属性
/**图片*/
@property (nonatomic, strong) NSString *icon;
/**名字*/
@property (nonatomic, strong) NSString *name;
/**下载量*/
@property (nonatomic, strong) NSString *download;
需要用到的成员属性
/**模型数组,用来存放每个cell的数据模型*/
@property (nonatomic, strong) NSArray *apps;
/**操作队列,操作只有添加到队列才有可能并发执行*/
@property (nonatomic, strong) NSOperationQueue *queue;
/**用于在内存中缓存图片,部分避免图片被多次下载*/
@property (nonatomic, strong) NSMutableDictionary *imageCache;
/**标记当前所有正在执行的操作,避免正在执行的操作被重复执行*/
@property (nonatomic, strong) NSMutableDictionary *operations;
创建cell的方法的核心代码
从内存缓存中取图片
//内存中缓存的图片在imagCache数组中
self.imageCache[app.icon]
从沙盒中取图片
//获取文件路径
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
//获取文件名
NSString *filename = [app.icon lastPathComponent];
//计算出全路径
NSString *file = [cachePath stringByAppendingPathComponent:filename];
//加载沙盒中的数据
NSData *data = [NSData dataWithContentsOfFile:file];
//判断data中若有数据,否则从网络上下载数据
if (data)
{//沙盒中有数据
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image = image;
//存到字典中(即内存)
self.imageCache[app.icon] = cell.imageView.image;
}
从网络上下载数据
//若subTitle类型的cell要显示图片,必须在第一次放回cell时就显示图片(或占位图片)
cell.imageView.image = [UIImage imageNamed:@"1"];
//取得操作队列中的操作
NSOperation *operation = self.operations[app.icon];
if (operation == nil)
{//不存在该图片的下载操作
//创建下载图片操作
operation = [NSBlockOperation blockOperationWithBlock:^{
//通过url加载数据
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];
//数据加载失败
if (data == nil)
{
//移除操作,以便刷新表格时能够再次请求数据
[self.operations removeObjectForKey:app.icon];
return ;
}
//NSData转换为UIImage
UIImage *image = [UIImage imageWithData:data];
//存放到字典中
self.imageCache[app.icon] = image;
//线程睡眠,模拟大数据下载
[NSThread sleepForTimeInterval:1];
//回主线程显示图片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//通过indexPath刷新表格,此时内存缓存中已有图片
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
//将图片写入沙盒
[data writeToFile:file atomically:YES];
//移除操作,保证在刷新表格时可以重新下载没有下载的图片
[self.operations removeObjectForKey:app.icon];
}];
//将操作添加到队列
[self.queue addOperation:operation];
//保证图片不被重复下载
self.operations[app.icon] = operation;
通过第三方框架(SDWebImage)
SDWebImage可以大大简化多图下载任务
通过扩展UIImageView的分类,在分类方法中实现多图下载功能,只给外部使用者暴露一个简单地网络接口
包含分类头文件UIImageView+WebCache.h
图片下载功能的实现
方法一
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
/**
url:图片的地址
placeholder:占位图片
*/
方法二
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock
/**
progressBlock:下载过程中的回调Block,可以在该Block中计算下载进度
completedBlock:下载完毕的回调方法
*/
iOS多线程-05-多图下载的更多相关文章
- ios开发多线程四:NSOperation多图下载综合案例
#import "ViewController.h" #import "XMGAPP.h" @interface ViewController () /** t ...
- 利用内存结构及多线程优化多图片下载(IOS篇)
利用内存结构及多线程优化多图片下载(IOS篇) 前言 下载地址, 后续发布, 请继续关注本blog 在IOS中,我们常常遇到多图片下载的问题.最简单的解决方案是直接利用别人写好的框架.但是这如同练武, ...
- 详解iOS多图下载的缓存机制
1. 需求点是什么? 这里所说的多图下载,就是要在tableview的每一个cell里显示一张图片,而且这些图片都需要从网上下载. 2. 容易遇到的问题 如果不知道或不使用异步操作和缓存机制,那么写出 ...
- iOS 多线程:『RunLoop』详尽总结
1. RunLoop 简介 1.1 什么是 RunLoop? 可以理解为字面意思:Run 表示运行,Loop 表示循环.结合在一起就是运行的循环的意思.哈哈,我更愿意翻译为『跑圈』.直观理解就像是不停 ...
- iOS 多线程:『GCD』详尽总结
本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法.这大概是史上最详细.清晰的关于 GCD 的详细讲解+总结的文章了.通过本文,您将了解到: 1. GCD 简介 2. GCD 任务和队列 ...
- iOS多线程技术方案
iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ...
- iOS多线程的详情使用示例--简进祥
大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ...
- iOS 多线程 浅述
什么是进程? 进程是指在系统中正在运行的一个应用程序. 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 什么是线程? 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程 ...
- iOS多线程开发
概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...
随机推荐
- 8月11日嵌入式Linux开发免费项目体验邀您参与
嵌入式Linux开发免费项目体验开课啦~~我们特意邀请到粤嵌金牌讲师和技术专家,为大家带来精彩有趣的嵌入式公开课,涉及到嵌入式学习.研发的方方面面.课堂中我们能体验到的不仅仅是最新资讯.技术体验,还有 ...
- 编写高质量JS代码的68个有效方法(四)
[20141129]编写高质量JS代码的68个有效方法(四) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...
- node log4js包
http://blog.csdn.net/heiantianshi1/article/details/43984601
- Mysql 修改密码及重置密码方法
修改密码: //选择数据库 use mysql; //修改密码 update user set password=password('新密码') where user='root'; //立即生效 f ...
- Laravel 5 多个视图共享数据的方法
我们都知道模板一般会用到继承,导航栏就是一个很好的例子,但是导航栏的数据如何共享,比如有个导航的文件叫在view/navigation.blade.php 为了简单一点,文件里只有设置了一个变量 {{ ...
- 资料下载:生活方向盘PPT以及活动录音(2011.02)
本文已挪至 http://www.zhoujingen.cn/blog/676.html 免费PDF和活动录音下载: http://down.51cto.com/data/216824 敏捷个人生活方 ...
- 最近读cocoaui源代码有感
上半年为了做一个ios的应用,引入了cocoaui库,主要是用来布局ios界面,发现简化了不少代码和工作量.因为在写第一个ios应用的时候,用的代码布局,在适配4s和6的机型时候,几乎被搞死,大量的约 ...
- python下的orm基本操作(1)--Mysql下的CRUD简单操作(含源码DEMO)
最近逐渐打算将工作的环境转移到ubuntu下,突然发现对于我来说,这ubuntu对于我这种上上网,收收邮件,写写博客,写写程序的时实在是太合适了,除了刚接触的时候会不怎么完全适应命令行及各种权限管理, ...
- 虚拟机service network restart没有反应解决方法
一般我们新copy的虚拟机或新克隆的虚拟机第一次启动时都会出现没有ip地址的情况: [root@zejin243 network-scripts]# ifconfig lo Link ...
- [Solution] 简单数字识别之Tesseract
图像识别涉及的理论:傅里叶变换,图形形态学,滤波,矩阵变换等等. Tesseract的出现为了解决在没有这些复杂的理论基础,快速识别图像的框架. 准备: 1.样本图像学习,预处理 (平均每1个元素出现 ...