最近两天,在完成工作业务之余,除了看书,自己也要开始深入的阅读经典的源码。来完善我的 iOS 源码探求 系列文章。
对源码的阅读是一个长久的学习过程,我会将业务中最常用的一些经典三方库拿出来进行学习。这一点我很敬佩 @Draveness 的精神,并向他看齐。
SDWebImage 简单介绍
SDWebImage 根据官方文档,其实就是提供了以下功能:
Asynchronous image downloader with cache support with an UIImageView category.
一个异步下载图片并且带有 UIImageView
Category 的缓存库。其好用的原因还在于其简介的接口。话不多说,开始主要内容。本系列文章使用的 SDWebImage 版本为 v3.8.1
。
多重入口委托构造器
在使用 SD 库的时候,最常调用的方法如下:
由此,对 UIImageView
的图片一部加载完成了。进入到该方法内部,在其 .h
的文件中看到以下接口:
作为 SD 的入口函数,在 sd_setImageWithURL 方法中采用了多种参数灵活搭配的同名方法。而内部实质,都在向最后一个 sd_setImageWithURL 传入参数最多的方法进行调用处理。
在 c++ 0x 中,这种方式被广泛的使用在系统库的 class 中作为类的委托构造器(Delegate Constructor)。这样做的好处是,可以清晰的梳理函数构造逻辑,减轻代码编写量。
setImageWithURL 处理流程
下面来看深入看一下上述代码注释中的 3 个要点。
- [self sd_cancelCurrentImageLoad]
进入函数内层是以下代码:
从代码中,可以看出:SD 使用 NSDictionary
来管理满足 SDWebImageOperation
代理的实例。通过对代理实例的判断,以及使用键值查询 operation 的方式,SD 可以有效、迅速的管理所有下载任务。
- objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
这里是使用关联对象(Associated Object)(如果这里陌生,可以查阅 浅谈Associated Objects 这篇博文),来对 UIImageView 做了一个关联值。在第二个参数上,一般是关联对象的唯一标记,在 UIImageView_WebCache.m 中使用了一个静态量地址来作为这个 key。
增加这个 url 属性便于在其他地方迅速访问。在获取时候,只需要调用 - (NSURL *)sd_imageURL
便可以直接通过关联对象迅速查询。这个 url 的访问在其他地方会有多次调用。
- completedBlock(image, error, cacheType, url);
默认情况下,SD 会等 image 完全从网络下载完成之后,直接替换 UIImageView 中的 image 。如果想在获取图片之后,手动处理之后的所有事情,则需要设置此方法。
这个方法是将会在 SDWebImageManager.h
出现。
setAnimationImagesWithURLs 图片组
在这个 Category 中,还有对于动画组图的设置。观看源码可知,这个方法在实现上是将多个图片的 URL 打包成 array,传入 sd_setImageLoadOperation
方法来增加图片加载的 Operation 。而在打包中,相当于多次执行了 sd_setImageWithURL
(其中的处理细节是一样的)。唯一不同的是,setAnimationImagesWithURLs
没有去设置关联对象。因为在展示中,我不需要对其做任何的控制,所以也就没有提供访问的快捷方法。
UIImageView+WebCache.m 源码解读总结
对于常用的 setImageWithURL
方法,可以总结成以下流程:
从最常用的 setImageWithURL
可以看出,其实 SDWebImage 的逻辑很清晰,其源码阅读起来可读性也很高。
在阅读三方库源码的同时,也可以感受到作者的代码经验所在。如同委托构造的方式,也是经验的积累总结。所以在学习代码的同时,也可以学习编码思想。
延伸阅读
cocoadocs SDWebImage
iOS 源代码分析—-SDWebImage