您的位置:首页 > 移动开发 > IOS开发

ios多图下载(多线程知识)

2016-03-16 22:38 513 查看

一 多图下载实现功能图



二 案例涉及到问题

01 字典转模型

02 图片重复下载—>内存缓存,沙盒缓存处理

03 UI不流畅—>开子线程下载图片(注意线程间通信)

04 图片下载任务被添加到队列中多次—>操作缓存处理

05 图片下载后不显示问题—>主动刷新指定行

06 图片加载中出现数据错乱问题—>设置占位图片

07 在程序开发过程中的一些容错处理

三 针对下载的图片处理思路

/*
需要解决的问题:
1> 先检查内存当中有没有图片
2> 如果有,就直接赋值
3> 如果没有,就到磁盘中寻找
4> 如果磁盘中有,就用磁盘中的
5> 如果磁盘中也没有,那么就缓存,下载
6> 检查是否有图片正在缓存
7> 如果有图片缓存,那么相同的图片就不再缓存了
8> 如果没有图片在缓存,那么就开始缓存图片
*/


四 代码部分

1 模型我这里就不过多的解释了,直接用KVC就能解决

2 主要针对每行cell中的图片处理

2.1 cell内容的前部分

static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
XFAppItem *item = self.arrayApps[indexPath.row];
//每行的标题
cell.textLabel.text = item.name;
//每行的下载次数
cell.detailTextLabel.text = item.download;


2.2 检查内存中是否存有已经下载好的图片,有的话就直接用内存的

//先去内存中找
//检查内存
UIImage *image = [self.images objectForKey:item.icon];
if (image) {
//如果内存中有就用内存的
cell.imageView.image = image;
}else{//接后面内存中没有图片的代码


2.3 检查磁盘,看磁盘中是相应的图片

//搜索图片的目录
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES)lastObject];

//得到图片名称
NSString *fileName = [item.icon lastPathComponent];

//拼接文件的全路径
NSString *fullPath = [cachesPath stringByAppendingPathComponent:fileName];

//如果缓存中没有,在到磁盘中找
NSData *data = [NSData dataWithContentsOfFile:fullPath];


2.4 如果磁盘中有存有的图片,那么就用磁盘里的,并且将图片保存到内存当中

//如果磁盘中有
if (data) {
UIImage *image = [UIImage imageWithData:data];
//设置cell的图片
cell.imageView.image = image;
//将图片存入内存中
[self.images setObject:image forKey:item.icon];
}else{//接磁盘中没有图片的代码部分


2.5 尝试着去取下缓存,看是否图片正在缓存,如果正在缓存,那么就不在另外缓存同样的图片了,if语句里面就什么都不做.但是不一定能取到

//检查图片是不是正在下载(尝试着去取一下缓存)
NSBlockOperation *downloadOperation = [self.operations objectForKey:item.icon];
//如果正在缓存,那么就什么都不做,让图片缓存
if (downloadOperation) {

}else{//接后面的不一定正在缓存


2.6 如果没有相应的图片在缓存,那么就让相应的图片缓存.开启子线程用于缓存下载图片,然后把图片保存到磁盘和内存

//如果没在缓存,就开一个子线程,用于缓存操作
downloadOperation = [NSBlockOperation blockOperationWithBlock:^{
//如果磁盘中没有,再下载

//获取图片地址
NSURL *url = [NSURL URLWithString:item.icon];
//下载图片二进制到本地
NSData *data = [NSData dataWithContentsOfURL:url];
for (NSInteger i = 0; i < 10000000; i++) {
}

//转换图片格式
UIImage *image = [UIImage imageWithData:data];

NSLog(@"1--------%@",[NSThread currentThread]);
//把图片保存到内存
[self.images setObject:image forKey:item.icon];

//把图片保存到磁盘
[data writeToFile:fullPath atomically:YES];


2.7 显示图片,这是属于显示UI界面,那么这种操作我们一般都是放到主线程中进行,回到主线程,刷新当前的cell

//回到主线程,设置图片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//                        cell.imageView.image = image;

//刷新指定的cell--->indexPath当前行
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
NSLog(@"%@-----------2",[NSThread currentThread]);
}];
}]


2.8 对缓存的一些操作,然后返回一个cell

//添加缓存操作到缓存当中
[self.operations setObject:downloadOperation forKey:item.icon];

//添加缓存到队列中
[self.queue addOperation:downloadOperation];


2.9 最后设置一个图片占位符.理由是因为当网速没有那么快的时候,只显示出来了标题和下载量,并没有图片,那样给用户的感觉不好,所以我们在图片还没有刷新出来之前先设置每一行cell的图片占位符.

代码写在2.5点的代码段上面

//设置一个占位图片
cell.imageView.image = [UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160316_1.png"];


五 解决的问题(主要问题)

1 UI界面卡顿

2 图片重复下载

3 用户每次滑动都会下载图片—–费流量

4 图片错乱

六 总结

本段代码逻辑很简单,就是可能代码写起来不是很流畅,大家多写几遍就可以了.有什么疑问,可以给我留言,谢谢!!!!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: