概要
学习SDWebImage后自己尝试写出的异步加载网络图片的库。从开始到完工经历大大小小的改版。
使用编程语言:Object-C。
功能:异步加载网络图片资源(图片、GIF)、加载本地GIF、渐进式下载图片。
如何使用
导入"UIImageView+URLImage.h",调用- (void)loadURLImageWith:(NSString*)url placeImage:(UIImage*)placeImage方法。
GitHub地址:https://github.com/zhangzecheng/URL-Image。 (欢迎大家下载提出宝贵建议,顺便点赞)
目前只对UIImageView进行添加分类加载网络图片。若其他控件也需要异步加载网络图片,可模仿代码中UIImageView的调用方法。
思路(贴图为最新代码)
一开始只是用NSData的dataWithContentsOfURL方法结合多线程,这样做的直观结果就是加载图片过程中APP不卡,可以顺畅的做其他操作。当另外的控件也需要加载这张图片时,却照样需要重走下载的流程。因此衍生出了缓存+沙盒的缓存机制。
加载图片的URL,先在缓存中查找是否下载过。没有则去沙盒中查找。若沙盒里也没有保存对应的图片资源(图片、GIF),则去下载队列里找,避免重复下载。此时将加载图片资源的回调(ZCImageCompletion)保存起来,再去判断是否已在下载队列中,没有在开启下载功能。
这三个公有方法便是整个异步加载的图片资源,为方便使用,已经将其写在一个方法里。
最初的“缓存”使用的是字典,可当APP内存不足时无法自动释放,由此使用NSCache替换。NSCache当APP内存警告时自动清除,这里不再赘述。
网络请求返回的data直接转为UIImage即可显示,保存到缓存、沙盒中;若是加载GIF,则需要用data去创建一个CGImageSourceRef,遍历CGImageSourceRef通过CGImageSourceCreateImageAtIndex拿到每一个CGImageRef,生成对应的UIImage,调用[UIImage animatedImageWithImages:imagesArrM duration:duration]来生成可加载GIF的UIImage。
由此,基本功能基本完成。但有个无关紧要的问题,便是当要加载的图片过大时,虽然可以使用占位图在APP上显示让界面不会有太多的空白。可有些需求是想看到加载的过程。由此变引入渐进式加载图片的功能。为了引入这个功能,对代码进行重新设计,剔除了“多线程+dataWithContentsOfURL”模式,引入了NSURLSession的类,用其进行网络图片资源的加载,并用ZCImageSource这个类来代表图片资源。
在NSURLSession的代理方法- (void)URLSession:(NSURLSession*)session dataTask:(NSURLSessionDataTask*)dataTask didReceiveData:(NSData*)data中,我们能拿到每次返回的数据,并将其拼接到之前已下载的data中,每次拿到data就将data转为UIImage,这就是渐进式加载图片的思路。