多图下载

多图下载综合案例

  • tableView- cell- cell上面有图标、标题、子标题
  • 图片来源:网络下载图片app.plist
  • 耗时操作,需要在子线程中执行

搭建界面

  • storyboard:tableViewController
    • is initial
    • class:ViewController
    • 描述cell
      • style:subtitle
      • indentifier
  • ViewController:UITableViewCotroller

数据展示

  • 提供数据源

    • 定义数组属性
    • 懒加载
      • 加载plist文件
      • 字典数组转成模型数组
        • 创建可变数组
        • 遍历字典数组
        • 把每一个字典转成模型
  • 创建模型

    • 模型属性name/icon/download
    • 提供一个类方法:appWithDict:
  • 实现数据源方法

    • 多少组
    • 每组有多少行
    • 定义cell视图
      • 创建cell
      • 设置cell数据:标题,子标题,图片
        • 图片下载
          • URL
          • 二进制数据下载到本地
          • 转换格式
      • 返回cell
  • 修改配置文件:ATS特性

缓存处理

  • 问题1:UI卡顿

    • 原因:把下载图片的耗时操作都放在主线程执行
    • 解决:开启子线程来下载图片
  • 问题2:拖动图片的时候,图片重复下载

    • 耗流量
    • 原因:滚动的时候会重新调用cellForRowAtIndextPath来显示图片
    • 解决:把下载的图片保存起来,下载图片之前,先检查本地有没有,如果有直接设置图片,就不重复下载了
  • 使用字典:一一对应

  • 定义一个可变字典属性

    • 懒加载,判断有没有做初始化处理,做初始化处理
  • 思路:当把图片下载图片完成之后,需要把该图片保存到内存缓存当中;在需要显示图片的时候,先检查本地的缓存中是否已经下载了该图片;如果缓存中有该图片,直接设置就可以了,如果缓存中没有该图片,此时需要去下载图片

  • 把图片保存到内存缓存

    • setObject:image forKey:name/dowload/icon
      • 建议用url作为key值
  • 尝试去字典里去取值,用key值去取

  • [self.images objectForKey:]

    • 如果有,设置图片
    • 如果没有,下载图片
  • 问题:保存到内存里了,是用属性接收图片的,退出程序后,重新运行程序,图片还是会重新下载

    • 怎么做到永远只下载一次
    • 如何改善缓存结构,改成二级缓存结构(沙盒缓存)

二级缓存结构

  • 【内存缓存 沙盒缓存】

  • 磁盘缓存(沙盒缓存)

    • 保存到内存缓存中的字典是变量,程序退出后就不存在了
    • 当图片下载完成之后,除了保存到内存缓存中之外,还需要保存一份到磁盘缓存中
    • 当图片需要显示的时候,先检查内存缓存,如果内存缓存中有数据,那么就直接设置数据
    • 如果内存缓存中没有数据,那么再去检查磁盘缓存
      • 怎么检查磁盘缓存?
        • 看路径对应的文件是否存在
        • 检查磁盘缓存dataWithContentOfFile:
    • 如果磁盘缓存中有数据,就直接设置就可以了 ,保存一份到内存缓存中
      • 显示图片
      • 保存一份到内存缓存中setObject:forKey
    • 如果没有数据,再去下载数据
  • 保存到磁盘的哪里?

    • Documents:备份,不允许存缓存
    • Library
      • caches:缓存文件一般存到这里
      • preference:偏好设置
    • tmp:临时路径,随时可能被删除
  • 步骤

    • 获得缓存路径NSSearchPathForDirectorieesInDomains()
      • NSCachesDirectory
      • NSUerDomainMask
      • YES
      • lastObject
    • 文件名称
      • NSURL拿到路径的最后一个节点
      • lastPathComponent
    • 拼接全路径
      • 文件路径+文件名称
      • stringByAppendingPathComponent:
    • 写文件
      • 图片是不能直接写文件的,数组和字典可以写文件
      • 拿到图片的二进制数据
      • data writeToFile:atomically:

开子线程下载图片

  • 创建队列NSOperationQueue
  • 封装操作
    • NSBlockOperation blockOperationWithBlock:
  • 添加操作到队列
  • UI刷新操作放到主线程
    • NSOperation mainQueue]addOperationWithBlock
  • 注意:在cellForRow中方法中创建了很多Queue,所以,定义一个属性,懒加载中创建队列
  • 问:为什么图片不显示?只有cell滚动的时候才能显示?
    • 最开始的时候图片的尺寸为0,imageView的大小是根据图片执行的
    • 操作是异步执行的,当cell要显示的时候调用cellForRow设置图片,开子线程下载是异步执行的,可以先跳过代码块,回过头来再执行
    • 解决:重新刷新,不能刷新整个tableView
      • 刷新一行reloadRowsAtIndexPaths:withRowanimation:

完善

  • 模拟下载该图片需要花费较长的时间,模拟网络不好的情况

  • bug:图片又重复下载

    • 分析:如果cell的第0个图片下载需要10s,在下载到第三秒的时候,拖动cell,第0行cell放到了缓存池中,当继续拖动cell,第0个cell又要显示的时候,又开始重新下载图片
    • 先检查图片的下载操作是否已经存在
      • 存在:等待
      • 不存在:封装图片下载操作并且添加到队列
        • 怎么判断不存在?尝试去取download
          NSBlockOperation * download = [self.operations objectForKey:appM.icon]
  • bug:当数据错乱的时候,程序容易崩溃

    • 数据后台传给我们的,当数据不对的时候,程序就会出现问题,会崩掉
    • 原因:把图片保存到内存缓存的时候,image是空[self.images setObject:image forKey:appM.icon];image为nil,字典里面是不能保存空值的
    • 解决:在设置之前判断image有没有值
  • bug:刷新tableView,数据错乱,显示图片和标题不对应

    • cell复用的问题
    • 两种方法解决数据错乱问题
      • 直接清空cell.imageView.image = nil,这样做法会给用户一种错觉,会认为cell本身没有图片
      • 设置一个占位图片,先搞一个本地的图片cell.imageView.image = [UIImage imageName:]
  • bug:图片没有下载图片没有下载成功,下载要显示的时候,要尝试重新下载,还需要把它从缓存中移除if(image ==nil){
    //从缓存池中移除
    [self.operations removeObjectForKey]
    return;
    }

  • 还需要细节的bug需要处理

SDWebImage实现

  • 专门处理图片下载和图片缓存的

  • 为Cocoa Touch框架提供一个UIImageView分类,加载图片进行缓存处理

  • 异步图片下载

  • 异步存储+具备自动缓存过期的磁盘映像缓存

  • 支持GIF播放

  • 支持WebP格式

  • 背景图像压缩

  • 保证同一个url图片资源不被多次下载

  • 保证错误url图片资源不被多次下载

  • 保证不会阻塞主线程

  • 高性能

  • 使用GCD和ARC

  • 支持arm64架构

  • 面试:框架内部实现细节

  • 中文文档SDWebImage-About框架的注释

  • SDWebImage

    • 改造多图下载项目
    • 一行代码
      • cell.imageView sd_setImageWithURL:placeholderImage:设置图片
      • 内部做了内存缓存和磁盘缓存
    • 图片尺寸的问题:
      • 框架本身的问题
      • 自定义cell里面设置图片的frame
        • layoutSubviews
      • 开发中cell一般都需要自定义,就可以在xib上设置frame了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容