zoukankan      html  css  js  c++  java
  • 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:下载完毕的回调方法
        */
        
  • 相关阅读:
    基于Debian的发行版Linux系统安装包命令
    戴尔服务器如何配置远程管理卡(IDRAC9)适用于戴尔R740服务器
    Tracert 命令
    Ubuntu 18.04 进入单用户模式修改密码
    华为eNSP模拟器— telnet实验
    华为交换机Console口属性配置
    Ubuntu 16.04 Bridge配置
    Ubuntu 16.04 配置单网卡绑定多IP
    springboot搭建web项目与使用配置文件
    读书笔记《SpringBoot编程思想》
  • 原文地址:https://www.cnblogs.com/theDesertIslandOutOfTheWorld/p/4762249.html
Copyright © 2011-2022 走看看