此为SDWebImage的源码阅读笔记


  1. 使用GCD时,如果需要比较两个线程是否相等的话,可以使用获取线程的label,然后比较的方法:
// SDWebImageCompat.h
// L104
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {//...
}
复制代码

上面的代码会判断当前的线程是否为主线程,因为对于UIImageView的更新的话需要发生在主线程上面。


Downloader

从模块名称我们能看出,这个模块是用于图片下载的。

  1. 下载选项
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {// 默认模式,SDWebImageDownloaderLowPriority = 1 << 0;// 渐进式下载,每接收到一段数据就会进行返回,可以一点一点显示图片SDWebImageDownloaderProgressiveDownload = 1 << 1;// 使用此标志的话,使用NSURLCacheSDWebImageDownloadUseNSURLCache = 1 << 2;// 如果图片是从NSURLCache中读取的话,在completion block中使用的图片参数数据是nilSDWebImageDownloaderIgnoreCachedResponse = 1 << 3;// 允许在app进入后台后,继续图片的下载SDWebImageDownloaderContinueInBackground = 1 << 4;// 处理NSHTTPCookieStore中的cookiesSDWebImageDownloaderHandleCookies = 1 << 5;// 允许使用不被信任的证书 SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6;// 将图片的下载放到优先级比较高的线程SDWebImageDownloaderHighPriority = 1 << 7;// 缩小图片SDWebImageDownloaderScaleDownLargeImages = 1 << 8;
}
复制代码
  1. SDWebImage提供了两种图片的下载顺序,分别是SDWebImageDownloadFIFOExecutionOrderSDWebImageDownloaderLIFOExecutionOrder。不难从名称中看出下载队列中图片的执行顺序。

  2. SDWebImageDownloadToken:每个下载都有一个token参数,可以根据token参数的值来取消对应的下载

  3. SDWebImageDownloader是一个同步图片下载和优化器(挑几个自己觉得重要的属性和方法)

  • shouldDecompressImage: 一个布尔值,默认是YES。表明在下载和缓存图片的过程中是否对图片进行解压操作,虽然可以优化图片的显示,但是会话费较多的内存。所以在内存不足的情况下,可以关闭这个属性
  • maxConcurrentDownloads:最大的并行下载数,默认值是6
  • downloadTimeout: 下载的超时时长,默认为15s
  1. SDWebImage内,在下载过程中,下载使用的线程是NSOperationNSOperationQueue组合,而处理下载操作的处理时,还有用到了GCD队列

  2. 下载器的session初始化:

self.session = [NSURLSession sessionWithConfiguration:sessionConfigurationdelegate:selfdelegateQueue:nil];
复制代码

delegate的处理队列传入的参数值是nil,传入nil的话,可以保证session创建一个串行队列来处理方法的调用。会根据图片的下载顺序,对队列中的操作添加依赖

  1. 在根据token的取值取消图片下载的时候,通过dispatch_barrier_async对操作队列进行barrier的操作

  2. 在添加回调block的时候,会在barrierQueue中进行同步操作,设置token相关的参数,并添加到操作字典URLOperations中。(SDWebImageDownloader - `addProgressCallback:completedBlock:forURL:createCallback:)

  3. SDWebImage中,通过继承NSOperation写了一个SDWebImageDownloaderOperation用于下载线程的管理。 在NSOperation中,作者将必要实现的方法抽象出来变成SDWebImageDownloaderOperationInterface,如果需要高度定制下载图片的话,需要实现接口的方法

  4. SDWebImageDownloaderOperation是一个并发操作

  5. (SDWebImageDownloaderOperation.m - L308)使用CGImageSourceCreateWithData将获取到的数据转化为CGImageSourceRef类型(作为data source),在每次获取到新的数据时,都需要拼接到原有的数据上,再传入到方法中,而不是只传入新的数据。

  6. (SDWebImageDownloaderOperation.m - L310 ~ L330)当通过NSURLSession的delegate获取到数据后,如果当前的图片宽和高信息均为0的话,则通过CGImageSourceCopyPropertiesAtIndex()方法获取到CFDictionaryRef的字典,根据kCGImagePropertyPixelHeight, kCGImagePropertyPixelWidthkCGImagePropertyOrientation可以获取到图片的宽,高和方向这三个值(获取图片方向的原因是因为通过Core Graphics绘制时,会丢失方向的参数)

  7. (SDWebImageDownloaderOperation.m - L332 ~ L377)使用CGImageSourceCreateImageAtIndex()来创建CGImage类型的image实例(记住要使用CGImageRelease()进行释放),接下来就是使用Core Graphics框架进行图片的绘制,关键的方法CGBitmapContextCreate()。关于使用Core Graphics进行图片绘制的相关知识的话,可以参考官网文档。这里就不详细介绍了:developer.apple.com/library/con…。当绘制成功之后,转化为UIImage对象,使用imageWithCGImage:scale:orientation来传入方向参数。最后根据需求对图片进行压缩。


Cache

Cache是SDWebImage用于缓存的模块。SDImageCache继承自NSObject,有内存缓存和硬盘缓存两种方式。对于硬盘缓存的话,在进行写操作的时候使用的是异步写入的方式。

  1. 图片的默认缓存时长为1周时间:`static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week

  2. 在进行图片缓存的时候,每张图片都有一个唯一的key值,以便对缓存进行查找,key值通常是图片的绝对路径

  3. 在进行缓存时,使用的是一个串行的IO队列来进行写入

  4. 在对SDImageCache进行初始化的时候,注册监听了三个通知:

  • 在接收到内存警告UIApplicationDidReceiveMemoryWarningNotification的时候,会清空内存缓存
  • 在app将要退出UIApplicationWillTerminateNotification的时候,会删除旧文件
  • 在进入后台UIApplicationDidEnterBackgroundNotification时,会在后台线程中删除旧文件
  1. 缓存时,会将图片的路径(即key值)进行MD5取值作为缓存的文件名
- (nullable NSString *)cachedFileNameForKey:(nullable NSString *)key {const char *str = key.UTF8String;if (str == NULL) {str = "";}unsigned char r[CC_MD5_DIGEST_LENGTH];CC_MD5(str, (CC_LONG)strlen(str), r);NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],r[11], r[12], r[13], r[14], r[15], [key.pathExtension isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", key.pathExtension]];return filename;
}
复制代码
  1. 硬盘缓存的存储路径是在'Library/Caches'路径下。默认情况下,如果没有取消缓存策略的话,都会在内存缓存中(NSCache *memCache)保存一份,对于硬盘存储的则是可选项.

  2. 从缓存获取图片的时候,首先会检查内存缓存,如果内存缓存中没有这张图片的话,就会检查硬盘缓存,如果硬盘缓存中没有,就会开始下载。但是,如果在硬盘缓存中命中的话,在返回图片的同时,会将图片缓存到内存中,提高查找效率。 想要移除图片的话,首先移除内存缓存中的数据,然后再移除硬盘缓存中的。 在SDWebImage中,对硬盘缓存的操作都是在ioQueue的GCD队列中进行异步操作,然后返回到主线程中执行block。避免对硬盘的读写操作会阻塞到主线程界面UI的更新

  3. 删除文件的时候,使用NSDirectoryEnumerator来获取文件的是否为文件夹的标志以及修改日期,大小的信息:

NSArray<NSString *> *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];// This enumerator prefetches useful properties for our cache files.NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURLincludingPropertiesForKeys:resourceKeysoptions:NSDirectoryEnumerationSkipsHiddenFileserrorHandler:NULL];
复制代码

然后根据修改日期和需要删除的图片的大小来进行旧文件的删除。


Utils

SDWebImageManager

  1. 在加载图片的过程中,SDWebImage提供几个相关的选项:
typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {/*** 默认情况下,当图片URL失效或者下载失败时,该URL会被添加到黑名单中并不会在尝试加载。* 此标志可以禁止URL被添加到黑名单中*/SDWebImageRetryFailed = 1 << 0,/*** 默认情况,图片的加载会发生在UI的交互期间。此标志位的话会将图片的加载延迟到UIScrollView滚动结束的期间*/SDWebImageLowPriority = 1 << 1,/*** 只将图片缓存到内存中*/SDWebImageCacheMemoryOnly = 1 << 2,/*** 开启进度下载,当有数据了将加载完成的那部分显示出来,默认情况的话,只会在图片完全加载完毕之后才将图片显示出来*/SDWebImageProgressiveDownload = 1 << 3,/*** 不管图片是否已经缓存,忽略HTTP响应的缓存控制并且刷新图片* 这个标志位的话可以用于同一个URL地址的图片,有的时候,虽然URL相同,但是图片如果有更新的话,缓存机制并不知晓这点。所以需要设置这个标志位来更新图片*/SDWebImageRefreshCached = 1 << 4,/*** 在iOS 4+, 允许app在进入后台后,继续下载图片。这会在app进入后台时,延长app的驻留时间,在这段时间中来完成图片的加载*/SDWebImageContinueInBackground = 1 << 5,/*** 通过将NSMutableURLRequest.HTTPShouldHandleCookies设置为YES来处理NSHTTPCookieStore中的cookie*/SDWebImageHandleCookies = 1 << 6,/*** 允许使用不被信任的证书*/SDWebImageAllowInvalidSSLCertificates = 1 << 7,/*** 默认情况下,图片会根据队列中的顺序进行加载,这个标志位的话会将图片的优先级提高,也就是将图片的前移*/SDWebImageHighPriority = 1 << 8,/*** 通常情况下,占位图片会在图片加载的过程中显示,这个标志位的话会将占位符延迟到图片加载完成后再进行占位符的加载*/SDWebImageDelayPlaceholder = 1 << 9,/*** 使用这个标志位来进行图片的变换*/SDWebImageTransformAnimatedImage = 1 << 10,/*** 图片通常会在加载完成后显示到imageView上。但是有时候,可以通过这个标志位来对图片进行修改之后再进行显示*/SDWebImageAvoidAutoSetImage = 1 << 11,/*** 默认情况,图片会根据原始的大小进行解码操作。在iOS中,会根据设备的内存限制进行缩小。*/SDWebImageScaleDownLargeImages = 1 << 12
};
复制代码
  1. 在下载图片过程中,如果是以下错误的话,则不会将图片URL添加到黑名单当中
  • NSURLErrorNotConnectedToInternet - 无法建立网络连接
  • NSURLErrorCancelled - 任务被取消了
  • NSURLErrorTimedOut - 超时
  • NSURLErrorInternationalRoamingOff - 无法建立漫游网络
  • NSURLErrorDataNotAllowed - 移动网络不允许建立连接
  • NSURLErrorCannotFindHost - 无法解析主机
  • NSURLErrorCannotConnectToHost - 连接主机时失败
  • NSURLErrorNetworkConnectionLost - 连接丢失

基本上从上述的错误原因能看到,当网络出现故障,无法连接到主机的时候,图片的URL不会被添加到黑名单当中,SDWebImage会尝试去重新连接下载

SDWebImageDecoder

  1. 使用CGBitmapContextCreate创建出来的上下文是不含有图片的透明度信息的

  2. decodedImageWithImage:方法实际上返回的就是去除了透明通道信息的图片

  3. 在解码图片时,默认情况下每一个像素还有4个字节


Categories

这个模块是其他Cocoa框架的类的Category

NSData+ImageContentType

通过获取NSData的图片数据的第一个字节来判断图片的格式

switch (c) {case 0xFF:return SDImageFormatJPEG;case 0x89:return SDImageFormatPNG;case 0x47:return SDImageFormatGIF;case 0x49:case 0x4D:return SDImageFormatTIFF;case 0x52:// R as RIFF for WEBPif (data.length < 12) {return SDImageFormatUndefined;}NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {return SDImageFormatWebP;}}
复制代码

UIImage+GIF

对于GIF图像的话,获取第一帧图片来显示,而完整的GIF图片的播放则由FLAnimatedImageView来完成。

UIImage中有一个images数组属性,对于GIF这种动态图片而言, images为非nil。所以根据这个变量是否为nil可以判断是否为GIF格式

UIImage+MultiFormat

UIImage+WebP

UIView+WebCacheOperation

为UIView添加了一个动态属性字典,用于存储图片的下载操作。


WebCache Categories

这个模块的主要功能是为控件添加图片加载的功能。通过核心方法sd_internalSetImageWithURL:placeholderImage:options:operationKey:setImageBlock:progress:completed:进行图片加载

转载于:https://juejin.im/post/5a30e29e6fb9a0451238f10c

SDWebImage 笔记相关推荐

  1. 美女图片采集器 源码+解析

    前言: 有一段时间没写博客了, "持之以恒"徽章都暗了, 实在不该. 前一段确实比较忙, ...小小地给自己的懒找个借口吧. 大二即将结束, 学习iOS也有一段时间了.今天抽点时间 ...

  2. 美女图片采集器 (源码+解析)

    前言: 有一段时间没写博客了, "持之以恒"徽章都暗了, 实在不该. 前一段确实比较忙, ...小小地给自己的懒找个借口吧. 大二即将结束, 学习iOS也有一段时间了.今天抽点时间 ...

  3. IOS开发笔记 - 基于SDWebImage的网络图片加载处理

    前言: 在IOS下通过URL读一张网络图片并不像Asp.net那样可以直接把图片路径放到图片路径的位置就ok, 而是需要我们通过一段类似流的方式去加载网络图片,接着才能把图片放入图片路径显示. 这里找 ...

  4. SDWebImage中文说明

    前端时间想详细的了解下AFNetworking库,所以想着看看官方的API吧.想想既然看看就做下笔记吧,既然做了笔记为何不试着翻译一下呢.然后就有了之前的文章<AFNetworking说明书&g ...

  5. 2019年年初iOS招人心得笔记(附面试题)

    从筛选第一份简历,准备面试题,到成功招到两个人一共花了两个星期多一点,总体来说还是比较顺利的.两位通过者都比较稳重踏实,而且对技术也比较有追求.这也可能和我筛选简历比较谨慎有关系,这次筛选简历所花费的 ...

  6. 阿里云rds for mysql平台介绍_阿里云RDS for MySQL 快速入门——笔记

    1初始化配置 1.1设置白名单 创建RDS实例后,需要设置RDS实例的白名单,以允许外部设备访问该RDS实例.默认的白名单只包含默认IP地址127.0.0.1,表示任何设备均无法访问该RDS实例. 设 ...

  7. iOS App Clips学习笔记

    一.什么是App Clip? App Clip是一个App的轻量版,用来提供一些用户所需功能,我们可以把它看成苹果的小程序.它不需要下载就直接能打开.这样即可达到不下载完整版APP便可体验APP的部分 ...

  8. SDWebImage 加载图片流程

    SDWebImage是老生常谈的三方,这篇博客算是一个笔记吧,记录下SDWebImage源码相关加载图片流程. 注1: 整体流程基于 SDWebImage 5.0.6 版本. 注2: 本文只对iOS执 ...

  9. iphone开发笔记和技巧总结

    在iphone程序中实现截屏的一种方法: //导入头文件   #importQuartzCore/QuartzCore.h //将整个self.view大小的图层形式创建一张图片imageUIGrap ...

最新文章

  1. 【AI】CelebA数据介绍、下载及说明
  2. python编程入门指南 明日科技-python从入门到项目实践明日科技三剑客书籍视频...
  3. 杭电1728bfs逃离迷宫java实现
  4. Postman安装与使用(网络请求神器)--post、get请求
  5. 猪场管理网站php,某养猪场网站整站 v1.1
  6. 20191226_1_淘宝口红商品分析
  7. 057 生成器和生成器表达式
  8. java 二进制乱码_深入解析java乱码
  9. 中信所怎么查期刊影响因子_《2019年版中国科技期刊引证报告(核心版)自然科学卷》医学类期刊目录(附影响因子)...
  10. linux 微信机器人,开源Linux操作系统的机器人(组图)
  11. Linux查看JDK版本和安装位置
  12. badboy linux 版本,jmeter/Badboy安装教程
  13. 计算机系和清华大学,清华大学交叉信息研究院和计算机系区别
  14. mysql最大tpmc_tpcc-mysql 压力测试 tpmc基准测试
  15. 三角形周长最短问题_三角形周长最短的动点问题
  16. Java学习之路-开局
  17. 家用 NAS 服务器搭建 | 前篇
  18. 【JavaScript】数据类型
  19. 微分,变分,差分的确切定义与区别
  20. 我是如何从汇编语言脑残粉转变的

热门文章

  1. 【解释】对用户透明=对用户隐蔽:关系模型的存取路径对用户透明
  2. 计算机的时间和dc的时间不同步_时间同步配置,让你轻松同步所有设备时间,让日志信息更有价值...
  3. MySQL 历史版本安装和下载
  4. tuxedo管理命令之tmadmin
  5. CSS学习总结3:CSS定位
  6. 基于gitosis的Git云端服务器配置
  7. python str函数isdigit、isdecimal、isnumeric的区别
  8. logrotate 切割 nginx php mysql 日志
  9. SQL优化--使用内连接(inner join)代替外连接(left join,right join) (转)
  10. 结构型设计模式(2)—— 外观模式(Facade Pattern)