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 图片错乱
六 总结
本段代码逻辑很简单,就是可能代码写起来不是很流畅,大家多写几遍就可以了.有什么疑问,可以给我留言,谢谢!!!!
相关文章推荐
- ios开发解决No known instance method for selector 'respondsToSelector:'的方法
- iOS中的事件传递和响应者链条
- iOS开发AssetsLibrary框架访问本地相册
- iOS之页面传值-----单例传值、通知传值
- ios json
- IOS 沙盒机制 浅析
- IOS 杂笔-2(协议)
- IOS 杂笔-1(为什么不继承类簇?)
- iOS的观察者模式
- iOS边练边学--自定义等高的cell
- iOS:使用block进行类与类,控制器与控制器之间的传值
- iOS 学习笔记-关于Button
- iOS之05-三大特性之封装
- Core Motion 加速器的使用步骤
- iOS启动屏 ➕ 闪屏的方法
- iOS多线程开发
- IOS开发之申请测试证书的步骤
- IOS动画
- ios--随笔二
- UVa 11111 - Generalized Matrioshkas