IOS之SDWebImage(附Demo)

目录

一、SDWebImage安装集成
 (1)安装
 (2)集成
二、SDWebImage原理说明
 (1)缓存的概念(计算机的存储方式、缓存的种类以及区别)
 (2)一级缓存和二级缓存的交互
 (3)二级缓存概念和作用
 (4)小结-->SDWebImage的缓存机制原理
三、SDWebImage源码实现步骤
 (1)常见的四种加载方式
 (2)加载步骤
 (3)清理缓存
 (4)系统默认清理缓存
(5)小节
四、总结

正文

一、SDWebImage安装集成

安装方式两种
1、直接cocoapods安装 在文件夹生成的podfile文件中添加pod 'SDWebImage' 终端cd + 文件位置 然后pod install即可
2、直接下载SDWebImage,然后将文件夹拖拽到本地项目即可.github托管地址https://github.com/rs/SDWebImage

集成
只需要导入头文件#import "UIImageView+WebCache.h"即可

二、SDWebImage原理说明

1、缓存的概念

什么叫缓存?
1、缓存是CPU的一部分,他存在于CPU中,CPU存取数据的速度非常快,一秒钟能够存取,处理十亿条指令和数据,而内存就很慢了,快的内存也就达到几十兆,两者速度差异很大。内存中被CPU访问最频繁的数据和指令被赋值入CPU中的缓存,这样需要缓存数据的时候就不用下载,直接取就可以了。
2、缓存只是内存中少部分数据的复制品,所以CPU在寻找数据的时候也会出现找不到的情况(因为这个数据没有从内存复制到缓存中去),这样系统的速度就慢下来了,不过CPU会把这些数据复制到缓存中去,以便下次不再从内存中取数据了。

计算机存在的存储方式都有哪种?(RAM和ROM)

RAM-RamdomAccessMemory易挥发性随机存取存储器,高速存取,读写时间相等,且与地址无关,如计算机内存等。 
ROM-Read Only Memory只读存储器。断电后信息不丢失,如计算机启动用的BIOS芯片。存取速度很低,(较RAM而言)且不能改写。由于不能改写信息,不能升级,现已很少使用。
ROM和RAM是计算机内存储器的两种型号,ROM表示的是只读存储器,即:它只能读出信息,不能写入信息,计算机关闭电源后其内的信息仍旧保存,一般用它存储固定的系统软件和字库等。RAM表示的是读写存储器,可其中的任一存储单元进行读或写操作,计算机关闭电源后其内的信息将不在保存,再次开机需要重新装入,通常用来存放操作系统,各种正在运行的软件、输入和输出数据、中间结果及与外存交换信息等,我们常说的内存主要是指RAM。

缓存的种类都有哪种?区别是什么?(SRAM和DRAM)

1、在RAM的概念当中也存在静态缓存(SRAM)和动态缓存(DRAM)
2、静态缓存的速度远远>动态缓存的速度
3、静态缓存的体积=6*动态缓存的体积(两者体积6倍关系)
4、静态缓存的价格=4*动态缓存的价格(两者价格4倍关系)

现在常见提高缓存速度的方式是什么?

增加二级缓存(二级缓存就是增加动态的RAM)——这里有人会问了,为什么不增加静态缓存呢(上面两者的对比已经列出,更何况缓存的存在就是为了减缓CPU访问内存的压力,所以无论是动态缓存还是静态缓存的增加都是为了缓解CPU的压力)

(2)一级缓存和二级缓存的交互、那么一级缓存和二级缓存的交互是怎样实现的呢?

1、存在都是为了减少高速CPU对慢速内存的访问
2、通常CPU找数据或指令的顺序是:先到一级缓存中找,找不到再到二级缓存中找,如果还找不到就只有到内存中找了

(3)二级缓存概念和作用
二级缓存到底是什么?它是干什么用的?

 二级缓存又叫L2 CACHE,它是处理器内部的一些缓冲存储器,其作用跟内存一样。 它是怎么出现的呢? 
要上溯到上个世纪80年代,由于处理器的运行速度越来越快,慢慢地,处理器需要从内存中读取数据的速度需求就越来越高了。
然而内存的速度提升速度却很缓慢,而能高速读写数据的内存价格又非常高昂,不能大量采用。
从性能价格比的角度出发,英特尔等处理器设计生产公司想到一个办法,就是用少量的高速内存和大量的低速内存结合使用,共同为处理器提供数据。
这样就兼顾了性能和使用成本的最优。而那些高速的内存因为是处于CPU和内存之间的位置,又是临时存放数据的地方,所以就叫做缓冲存储器了,简称“缓存”。
它的作用就像仓库中临时堆放货物的地方一样,货物从运输车辆上放下时临时堆放在缓存区中,然后再搬到内部存储区中长时间存放。货物在这段区域中存放的时间很短,就是一个临时货场。
最初缓存只有一级,后来处理器速度又提升了,一级缓存不够用了,于是就添加了二级缓存。
二级缓存是比一级缓存速度更慢,容量更大的内存,主要就是做一级缓存和内存之间数据临时交换的地方用。现在,为了适应速度更快的处理器P4EE,已经出现了三级缓存了,它的容量更大,速度相对二级缓存也要慢一些,但是比内存可快多了。
 缓存的出现使得CPU处理器的运行效率得到了大幅度的提升,这个区域中存放的都是CPU频繁要使用的数据,所以缓存越大处理器效率就越高,同时由于缓存的物理结构比内存复杂很多,所以其成本也很高。

4、小结--> SDWebImage的缓存机制

typedef NS_ENUM(NSInteger, SDImageCacheType) {
    /**
     * The image wasn't available the SDWebImage caches, but was downloaded from the web.(这张图片没有提供SDWebImage缓存,但从网上下载。)
     */
    SDImageCacheTypeNone,
    /**
     * The image was obtained from the disk cache.(图像是从磁盘缓存中获得的。)
     */
    SDImageCacheTypeDisk,
    /**
     * The image was obtained from the memory cache.(图像是从内存缓存中获得的。)
     */
    SDImageCacheTypeMemory
};

SDWebImage底层实现缓存机制,主要由三块组成
1、网络下载获取(当缓存中寻找不到的情况下->下载完之后会自动存储到好磁盘缓存中)
2、磁盘缓存获取
3、内存缓存获取

这里 SDImageCache维护一个内存缓存和一个可选的磁盘缓存。磁盘缓存写操作是异步执行的,所以它不会给UI增加不必要的延迟
原理如下------

1)当我门需要获取网络图片的时候,我们首先需要的便是URL,获得URL后我们SDWebImage实现的并不是直接去请求网路,而是检查图片缓存中有没有和URl相关的图片,如果有则直接返回image,如果没有则进行下一步。

2)当图片缓存中没有图片时,SDWebImage依旧不会直从网络上获取,而是检查沙盒中是否存在图片,如果存在,则把沙盒中对应的图片存进image缓存中,然后按着第一步的判断进行。

3)如果沙盒中也不存在,则显示占位图,然后根据图片的下载队列缓存判断是否正在下载,如果下载则等待,避免二次下载。如果不存则创建下载队列,下载完毕后将下载操作从队列中清除,并且将image存入图片缓存中。

4)刷新UI(当然根据实际情况操作)将image存入沙盒缓存。


源于网络
三、SDWebImage源码实现步骤

常见的四种加载方式

1、无占位图直接加载(如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)

- (void)sd_setImageWithURL:(nullable NSURL *)url {
    [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}

2、有占位图直接加载(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)

- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
    [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
}

3、有占位图直接加载,并且实现图片加载完之后的Block可以继续完成下一步操作(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)

- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
    [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
}

4、可以选择options的形式加载图片,(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)

- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
    [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}

/*使用可更换optionsType的加载方式
 
                    -------------Options 枚举下的加载方式-----------
 SDWebImageRetryFailed 默认情况下,当URL无法下载时,URL就会被列入黑名单,这样库就不会继续尝试了。此标记禁用此黑名单。
 SDWebImageLowPriority  默认情况下,图像下载是在UI交互过程中启动的,这标志禁用该特性,导致在UIScrollView减速方面延迟下载。
 SDWebImageCacheMemoryOnly  此标记禁用磁盘缓存
 SDWebImageProgressiveDownload 此标志可以进行渐进式下载,在下载过程中,图像会逐步显示,就像浏览器所做的那样。默认情况下,图像只显示一次完全下载。
 SDWebImageRefreshCached  即使缓存了映像,也要尊重HTTP响应缓存控制,并在需要的情况下从远程位置刷新映像。磁盘缓存将由NSURLCache来处理,而不是使用SDWebImage,这会导致轻微的性能下降。这个选项有助于处理在同一个请求URL后面更改的图像,例如Facebook图形api概要图。如果刷新了缓存的图像,那么完成块就会被缓存的图像和最后的图像再次调用一次。只有当你不能用嵌入的缓存破坏参数使你的url静态时,才使用这个标志。
 SDWebImageContinueInBackground  在iOS 4+中,如果应用程序进入后台,可以继续下载图片。这是通过请求系统在后台获得额外的时间来完成请求完成的。如果后台任务过期,操作将被取消。
 SDWebImageHandleCookies 通过设置NSMutableURLRequest来处理存储在NSHTTPCookieStore中的cookie。HTTPShouldHandleCookies =是的;
 SDWebImageAllowInvalidSSLCertificates  启用不受信任的SSL证书。用于测试目的。在生产中使用谨慎。
 SDWebImageHighPriority 默认情况下,图像按顺序装载在队列中。这个标志把它们移到队列的前面。
 SDWebImageDelayPlaceholder  默认情况下,在图像加载时加载占位符图像。此标志将延迟加载占位符图像,直到图像完成加载。
 SDWebImageTransformAnimatedImage   我们通常不会在动画图像上调用transformdownloade昏暗委托方法,因为大多数转换代码会把它搞砸。无论如何,使用这个标志来转换它们。* /
 SDWebImageAvoidAutoSetImage  默认情况下,图像会在下载后添加到imageView中。但是在某些情况下,我们想要在设置图像之前有手(例如,应用一个过滤器或将它添加到交叉衰减动画中)使用这个标记如果你想在成功完成时手工设置图像
 SDWebImageScaleDownLargeImages  默认情况下,图像会被解码,以尊重它们原来的大小。在iOS上,这一标志将把图像缩小到与设备受限内存兼容的大小。*如果“SDWebImageProgressiveDownload”标志设置禁用缩减。
 */

以上四个常用方法,点击进去查看内部实现代码时,你会发现所有方法都指向------>

内部实现

源码注释解释的含义是

用url、占位符和自定义选项设置imageView图像。下载是异步的和缓存的。
@param url是图像的url。
@param占位符将首先设置的图像,直到图像请求完成。
@param选择在下载图像时使用的选项。
@参见SDWebImageOptions用于可能的值。
@param progressBlock在下载@note时,在后台队列
@param completedBlock的后台进程中执行进程块,该块是在操作完成时被调用的。这个块没有返回值,并将所请求的UIImage作为第一个参数。在出现错误时,图像参数为nil,第二个参数可能包含一个NSError。第三个参数是一个布尔值,指示是否从本地缓存或网络检索图像。第四个参数是原始图像url。

下面是图解(上面展示了每句话的备注)

1、设置展位图,并且取消当前下载任务


图解

2、创建一个新的下载操作


下载图片的回调

3、下载操作代码(判断流是否存在,如果不存在则将其存在失效列表中,防止重复下载无效流)-----在这里他对NSString和NSURL的转换做了判断。原因是(非常常见的错误是使用NSString对象而不是NSURL发送URL。出于某种奇怪的原因,Xcode不会对这种类型的不匹配发出任何警告。在这里,我们通过允许url作为NSString传递来确保这个错误。)括号当中是文档给出的解释,所以这里做了强制转换。


下载操作代码 判断URL类型

4、利用唯一生成的key,到缓存--->内存---->磁盘中分别寻找。
利用唯一生成的key,到缓存--->内存---->磁盘中分别寻找。

5、寻找的顺序 缓存---->磁盘---->在没有就下载

首先判断缓存和磁盘中是否存在

下载流程之后就是清理缓存(种类) 1、清理所有内存缓存镜像 2、清理所有磁盘缓存镜像3、清理过期的缓存映像从磁盘中删除

/*
     异步清除所有磁盘缓存映像。非阻塞方法-立即返回。@param完成一个应该在缓存过期后执行的块(可选)
     
     注意:这里要注意[[SDImageCache sharedImageCache] clearDisk];方法会报错,下面clearDiskOnCompletion的方法会替代上面的方法
     */
    [[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
        
    }];
    
    /*
     Clear all memory cached images --->清除所有缓存镜像
     */
    [[SDImageCache sharedImageCache] clearMemory];
    
    /*
     异步将所有过期的缓存映像从磁盘中删除。非阻塞方法-立即返回。@param completionBlock在缓存过期后执行(可选)--->故名思义他是不能删除你当前缓存的大小的
     */
    [[SDImageCache sharedImageCache] deleteOldFilesWithCompletionBlock:^{
        
    }];

当然清理的方式不仅仅手动操作. ------> SDWebImage自动也会清理内存,默认周期为一周

小节

1、如果在加载图片的过程中出现程序报错(App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.)
你需要操作如下--------
(1)、在Info.plist中添加 NSAppTransportSecurity 类型 Dictionary ;
(2)、在 NSAppTransportSecurity 下添加 NSAllowsArbitraryLoads 类型Boolean ,值设为 YES;

2、SDWebImage通过唯一镜像的方式查找图片的顺序如下---

内存缓存 ------->磁盘缓存 ------>通过URL下载图片并且存储到磁盘当中。


流程--源于网络

小结-->


1.setImageWithURL:placeholderImage:options:  
会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始 处 图 。 
2.进SDWebImageManagerdownloadWithURL:delegate:options:userInfo:,  交给 SDImageCache 从缓存查找图 是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
3.先从内存图 缓存查找是否有图 ,  如果内存中已经有图 缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。  
4.SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 
到 UIImageView+WebCache 等前端展示图 。
5.如果内存缓存中没有, 成 NSInvocationOperation   添加到队 开始从硬盘查找图 是否已经缓存。 
6.根据 URLKey 在硬盘缓存 录下尝试读取图  件。 
这 步是在 NSOperation 进 的操作,所以回主线程进 结果回调 notifyDelegate:
7.如果上 操作从硬盘读取到 图 ,将图 添加到内存缓存中   (如果空闲内存过 ,会先清空内存缓存)。  
SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。  进 回调展示图 。 
8.如果从硬盘缓存 录读取 到图 ,  说明所有缓存都 存在该图 ,需要下载图 , 
回调 imageCache:didNotFindImageForKey:userInfo:。  
9.共享或重新 成 个下载  SDWebImageDownloader 开始下载图 。
10.图 下载由 NSURLConnection 来做, 
实现相关 delegate 来判断图 下载中、下载完成和下载失败。  
11.connection:didReceiveData: 中  ImageIO 做 按图 下载进度加载效果。  
12.connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图 解码处 。 
13.图 解码处 在 个 NSOperationQueue 完成, 
 会拖慢主线程 UI。如果有需要对下载的图 进  次处 ,  最好也在这 完成,效率会好很多。 
14.在主线程 notifyDelegateOnMainThreadWithInfo:  
宣告解码完成,  imageDecoder:didFinishDecodingImage:userInfo: 
回调给 SDWebImageDownloader。  15.imageDownloader:didFinishWithImage: 
回调给 SDWebImageManager 告知图 下载完成。  16.通知所有的 downloadDelegates 下载完成,  回调给需要的地 展示图 。 
17.将图 保存到 SDImageCache 中,  内存缓存和硬盘缓存同时保存。  写 件到硬盘也在以单独 NSInvocationOperation 完成,  避免拖慢主线程。 
18.SDImageCache 在初始化的时候会注册 些消息通知, 
在内存警告或退到后台的时候清 内存图 缓存,  应 结束的时候清 过期图 。 
19.SDWI 也提供  UIButton+WebCache 和   MKAnnotationView+WebCache
20.SDWebImagePrefetcher 可以预先下载图 ,后续使 。 

总结

SDWebImage作为一个优秀的图片加载框架
1、大量的block回调,可能看起来并没有那么直观
2、都采用异步的操作方式
3、报漏方法简单易懂(开文中说的四种常见展示图片的方法)

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

推荐阅读更多精彩内容