iOS老司机的框架设计心得Tips_图片缓存框架

3,054 阅读4分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

  • 图片缓存在iOS端我们可能每天都会使用, Objective-C中有SDWebImage, Swift中有喵神的Kingfisher~
  • 然而会使用框架提供的API只是表层, 如果想精进自己的框架设计能力, 我们还需要去研究框架源码, 以窥这些顶级开发者的设计思路.
  • 下面就iOS中的图片缓存框架, 跟各位同仁聊一聊自己的浅见, 抛砖引玉.
  • 文章纯手打, 抛砖引玉, 如有错误还请评论区指正, 先行谢过了:)

1. 一个合理的图片缓存框架应该考虑什么?

1.1 怎样设计一个图片缓存框架?

  • 我们需要考虑以下几点:
    • Manager
    • 内存 磁盘 网络
    • Code Manager
    • 图片解码 图片压缩/解压缩

1.2 图片读写应该如何设计?

  • 以图片URL的单向Hash值作为Key
  • 开始 -> 内存是否命中
  • YES -> 结束
  • NO -> 磁盘是否命中
    • YES -> 结束
    • NO -> 网络下载 -> 结束

1.3 内存层面应该如何设计?

1.3.1 存储的Size

  • 队头 队尾
  • 50 x 10kb以下
  • 20 x 100kb以下
  • 10 x 100kb以上

1.3.2 图片的淘汰策略

  • 以队列先进先出的方式淘汰
  • LRU算法(如30分钟内是否使用过)
    • 定时检查 提高检查触发频率
    • 每次进行读写时 前后台切换时
    • 这里一定注意开销!

1.3.3 磁盘存储层面的设计

  • 存储方式
  • 大小限制(如100MB)
  • 淘汰策略(如某一图片存储时间距今已超过7天)

1.3.4 网络请求层面的设计

  • 图片请求最大并发量
  • 请求超时策略
  • 请求优先级

1.3.5 图片解码层面的考量

  • 对于不同格式的图片, 解码采用什么方式来做?
  • 应用策略模式对不同图片格式进行解码
  • 在哪个阶段做图片解码处理?
  • 磁盘读取后 网络请求返回后

1.3.6 整体思路导图

image.png

2. iOS中的SDWebImage框架是怎么做缓存的?

  • 采用了二级缓存策略, 图片缓存的时候, 在内存中有缓存, 在磁盘中也有缓存
  • 内存缓存使用NSCache做的.

2.1 缓存步骤

  1. 下载图片, 将图片缓存在内存中
  2. 判断图片的格式为png或jpeg, 将图片转成NSData数据
  3. 获取图片的存储路径, 图片的文件名是通过传入key经过MD5加密后获得的
  4. 将图片存进磁盘中

2.2 如何获取图片

  1. 在内存缓存中找
  2. 如果内存中找不到, 去默认磁盘目录中找, 找不到在去自定义磁盘目录中找
  3. 如果磁盘中也找不到就会下载图片
  4. 获取图片数据之后, 根据图片类型将图片数据从NSData转成UIImage
  5. 默认对图片进行解压缩, 生成位图图片
  6. 将位图图片返回

2.3 图片是如何被解压缩的?

  1. 判断图片是否是动图, 如果是就不能解压缩
  2. 判断图片是否透明, 如果是, 不能解压缩
  3. 判断图片的颜色控件是不是RGB, 如果不是, 就不能解压缩
  4. 根据图片的大小创建一个上下文
  5. 将图片绘制在上下文中
  6. 从上下文中读取一个不透明的位图图像, 该图像就是解压缩后的图像
  7. 将位图图像返回

2.4 NSCache

  • NSCache说白了就是做缓存专用的一个系统类
  • 类似可变字典一样, 但是NSCache是线程安全的, 系统类自动做好了加锁和释放锁等一系列的操作,
    • 还有一个重要的是如果内存不足的时候, NSCache会自动释放掉存储的对象, 不需要开发者手动干预.

2.5 SDWebImage是如何解决tableView复用时出现图片错乱问题的?

  • 错乱是在UIImageView+WebCache文件中这个方法每次都会调用[self sd_cancelCurrentImageLoad].

2.6 SDWebImage大致流程导图

image.png

3. 小结

  • 图片缓存框架的设计思路及应用基本就是以上这些.
  • 在使用这些框架的时候, 知道这些框架的设计思路, 可能也并不会提高太多开发效率.
  • 认识框架底层背后的设计思路, 在我看来是提供了一种技术冗余积累.
  • 因为, 你我都无法保证在三方框架的时候过程中, 可能会遇到什么突发情况.
  • 然而知其所以然后, 我们在处理这些突发情况时, 就能更加从容:)

发文不易, 喜欢点赞的人更有好运气👍 :), 定期更新+关注不迷路~

ps:欢迎加入笔者18年建立的研究iOS审核及前沿技术的三千人扣群:662339934,坑位有限,备注“掘金网友”可被群管通过~

本文正在参加「金石计划 . 瓜分6万现金大奖」