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:下载完毕的回调方法
    */

本博客的最新状态将会同步到新浪微博账号:世俗孤岛

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 22:56:45

iOS多线程-05-多图下载的相关文章

iOS开发网络多线程之多图下载

一. ?多线程中多图片下载 头像通过网络下载得到 效果图如下: 二. 设计思路 ?利用tableView实现多行数据的现实,图标通过网络下载很耗时,需要在子线程中执行. ?cell中的ImageView的设置: 1. 首先到图片缓存池中取(定义一个存放图片的的字典属性),如果有直接设置; 2. 如果图片缓存池没有,再到沙盒缓存cache中查看是否存在,如果有直接设置,并把沙盒中的图片写入到图片缓存池中 3. 如果沙盒cache中也没有,就需要开线程下载; 4. 首先判断当前图片是否有任务在下载(

ios开发多线程四:NSOperation多图下载综合案例

#import "ViewController.h" #import "XMGAPP.h" @interface ViewController () /** tableView的数据源 */ @property (nonatomic, strong) NSArray *apps; /** 内存缓存 */ @property (nonatomic, strong) NSMutableDictionary *images; /** 队列 */ @property (no

iOS多线程自定义operation加载图片 不重复下载图片

摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用:   2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验   2:自定义operation继承自NSOperation,在子线程中下载图片: 3:保证图片只下载一次,还有保证下载任务不重复 ------------------------------------------------------------------------------------ 实现原理:1:图片缓存:用

iOS教程:详解iOS多图下载的缓存机制

ios教程,ios的干货一直来不及给大家分享,小编也是一直在忙啊!今天给大家献上ios:详解iOS多图下载的缓存机制 1. 需求点是什么? 这里所说的多图下载,就是要在tableview的每一个cell里显示一张图片,而且这些图片都需要从网上下载. 2. 容易遇到的问题 如果不知道或不使用异步操作和缓存机制,那么写出来的代码很可能会是这样: cell.textLabel.text = app.name; cell.detailTextLabel.text = app.download;NSDat

详解iOS多图下载的缓存机制

1. 需求点是什么? 这里所说的多图下载,就是要在tableview的每一个cell里显示一张图片,而且这些图片都需要从网上下载. 2. 容易遇到的问题 如果不知道或不使用异步操作和缓存机制,那么写出来的代码很可能会是这样: cell.textLabel.text = app.name; cell.detailTextLabel.text = app.download;NSData *imageData = [NSData dataWithContentsOfURL:app.url]; cell

iOS 多线程:『GCD』详尽总结

本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法.这大概是史上最详细.清晰的关于 GCD 的详细讲解+总结的文章了.通过本文,您将了解到: 1. GCD 简介 2. GCD 任务和队列 3. GCD 的使用步骤 4. GCD 的基本使用(6种不同组合区别) 5. GCD 线程间的通信 6. GCD 的其他方法(栅栏方法:dispatch_barrier_async.延时执行方法:dispatch_after.一次性代码(只执行一次):dispatch_once.快速迭代方法:dis

线程同步-iOS多线程编程指南(四)-08-多线程

首页 编程指南 Grand Central Dispatch 基本概念 多核心的性能 Dispatch Sources 完结 外传:dispatch_once(上) Block非官方编程指南 基础 内存管理 揭开神秘面纱(上) 揭开神秘面纱(下) iOS多线程编程指南 关于多线程编程 线程管理 Run Loop 线程同步 附录 Core Animation编程指南 Core Animation简介 基本概念 渲染架构 几何变换 查看目录 中文手册/API ASIHTTPRequest Openg

iOS 多线程详解

iOS开发 多线程 概览 机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种状况可以从两个角度出发: 对于单核处理器,可以将多个步骤放到不同的线程,这样一来用户完成UI操作后其他后续任务在其他线程中,当CPU空闲时会继续执行,而此时对于用户而言可以继续进行其他操作: 对于多核处理器,如果用户在UI线程中完成某个操作之后,其他后续操作在别的线程中继续执行,用户同样可以继续进行其他UI操作,与此同时前一个操作的后续任务可以分散到多个空闲CPU中继续执行(当然具体调度顺序要根据

iOS多线程 NSThread/GCD/NSOperationQueue

http://www.cnblogs.com/kenshincui/p/3983982.html iOS开发系列--并行开发其实很容易 2014-09-20 23:34 by KenshinCui, 9738 阅读, 19 评论, 收藏,  编辑 --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种