SDWebImage的知名度就不用說了棒厘,github上近10k的star,國內(nèi)外太多的App使用其進(jìn)行圖片加載下隧。簡(jiǎn)單介紹一下奢人,它是一個(gè)圖片框架,支持從網(wǎng)絡(luò)中下載且緩存圖片淆院,并設(shè)置圖片到對(duì)應(yīng)的UIImageView 控件或者 UIButton 控件何乎。使用SDWebImage來管理圖片加載,會(huì)極大地提高我們的開發(fā)效率土辩,從而讓我們更加專注于業(yè)務(wù)邏輯實(shí)現(xiàn)支救。也正是因?yàn)檫@樣,讓我們很多開發(fā)都只會(huì)用SDWebImage拷淘,而忽略了它的內(nèi)部實(shí)現(xiàn)各墨,今天我就給大家介紹一下SDWebImage的內(nèi)部實(shí)現(xiàn)及原理。
一启涯、SDWebImage 概述
SDWebImage是一個(gè)開源的第三方庫贬堵,它提供了UIImageView的一個(gè)分類,以支持從遠(yuǎn)程服務(wù)器下載并緩存圖片的功能结洼。它具有以下功能:
1黎做、提供了一個(gè)UIImageView的 category用來加載網(wǎng)絡(luò)圖片,并對(duì)網(wǎng)絡(luò)圖片的緩存進(jìn)行管理松忍。
2蒸殿、采用異步方式來下載網(wǎng)絡(luò)圖片
3、采用異步方式鸣峭,使用 memory+disk 來緩存網(wǎng)絡(luò)圖片伟桅,自動(dòng)管理緩存。
4叽掘、支持 GIF 動(dòng)畫
5楣铁、支持 WebP 格式
6、同一個(gè) URL 的網(wǎng)絡(luò)圖片不會(huì)被重復(fù)下載
7更扁、失效的 URL 不會(huì)被無限重試
8盖腕、耗時(shí)操作都在子線程,確保不會(huì)阻塞主線程
9浓镜、使用 GCD 和 ARC
10溃列、支持 Arm64
二、SDWebImage 使用
1膛薛、使用 ImageView+WebCache category 來加載 網(wǎng)絡(luò)圖片
2.听隐、使用Blocks,在 block 中得到圖片下載進(jìn)度和圖片加載完成(下載完成或者讀取緩存)的回調(diào),如果你在圖片加載完成前取消了請(qǐng)求操作哄啄,就不會(huì)收到成功或失敗的回調(diào)
3雅任、使用SDWebImageManager,SDWebImageManager為UIImageView+WebCache category的實(shí)現(xiàn)提供下載圖片接口风范。
4、單獨(dú)使用 SDWebImageDownloader 來下載圖片沪么,但是圖片內(nèi)容不會(huì)緩存硼婿。
5、使用 SDImageCache 異步緩存圖片
SDImageCache 同時(shí)緩存到內(nèi)存和磁盤中禽车。
SDImageCache 只緩存到內(nèi)存:
讀取緩存時(shí)可以使用 queryDiskCacheForKey:done: 方法寇漫,圖片緩存的 key 是唯一的,通常就是圖片的 absolute URL殉摔。
6州胳、清除緩存文件
7、獲取所有緩存圖片的總大小
8逸月、獲取緩存圖片張數(shù)
9陋葡、直接從緩存中提取圖片
10、直接刪除緩存中得圖片
11彻采、判斷本地緩存中是否存在網(wǎng)絡(luò)中的圖片
在實(shí)際的運(yùn)用中腐缤,我們并不直接使用SDWebImageDownloader類及SDImageCache類來執(zhí)行圖片的下載及緩存。為了方便用戶的使用肛响,SDWebImage提供了SDWebImageManager對(duì)象來管理圖片的下載與緩存岭粤。而且我們經(jīng)常用到的諸如UIImageView+WebCache等控件的分類都是基于SDWebImageManager對(duì)象的。該對(duì)象將一個(gè)下載器SDWebImageDownloader和一個(gè)圖片緩存SDImageCache綁定在一起特笋,并對(duì)外提供兩個(gè)只讀屬性來獲取它們剃浇。
三、實(shí)現(xiàn)原理
1猎物、SDWebImage 流程圖
2虎囚、核心邏輯
1、UIImageView+WebCache 中最核心的方法 sd_setImageWithURL: placeholderImage: options: progress: completed:蔫磨。給UIImageView設(shè)置圖片淘讥,就是調(diào)用此方法,方法內(nèi)部的具體做以下幾件事:
- 取消當(dāng)前正在進(jìn)行的加載任務(wù) operation
- 設(shè)置 placeholder
-
如果 URL 不為 nil堤如,就通過 SDWebImageManager 單例開啟圖片加載任務(wù) operation蒲列,SDWebImageManager 的圖片加載方法中會(huì)返回一個(gè) SDWebImageCombinedOperation 對(duì)象,這個(gè)對(duì)象包含一個(gè) cacheOperation 和一個(gè) cancelBlock搀罢。
a.開始加載之前蝗岖,先取消對(duì)應(yīng)的UIImageView先前的圖片下載操作±浦粒框架將對(duì)應(yīng)的下載操作放在UIView的一個(gè)自定義字典屬性(operationDictionary)中抵赢,取消下載操作第一步也是從這個(gè)UIView的自定義字典屬性(operationDictionary)中取出所有的下載操作,然后依次調(diào)用取消方法,最后將取消的操作從(operationDictionary)字典屬性中移除铅鲤。
b.移除之前沒用的圖片下載操作之后就創(chuàng)建一個(gè)新的圖片下載操作划提,然后設(shè)置到UIView的一個(gè)自定義字典屬性(operationDictionary)中。創(chuàng)建一個(gè)新的圖片下載操作,框架保存了一個(gè)失效的URL列表彩匕,如果URL失效了就會(huì)被加入這個(gè)列表腔剂,保證不會(huì)重復(fù)多次請(qǐng)求失效的URL媒区。根據(jù)給定的URL生成一個(gè)唯一的Key,之后利用這個(gè)key到緩存中查找對(duì)應(yīng)的圖片緩存驼仪。
c.讀取圖片緩存,先拿圖片緩存的 key去內(nèi)存中讀取緩存,如果有袜漩,就返回給 SDWebImageManager 绪爸;如果內(nèi)存沒有緩存,就開啟異步線程去磁盤開始讀取宙攻,如果有就從磁盤同步到內(nèi)存中去奠货,再返回給SDWebImageManager 。如果內(nèi)存和磁盤中都沒有座掘,SDWebImageManager 就會(huì)調(diào)用 downloadImageWithURL: options: progress: completed: 方法去下載递惋。
d.在圖片下載方法中,調(diào)用了一個(gè)方法用于添加創(chuàng)建和下載過程中的各類Block回調(diào)溢陪。
e.如果該URL是第一次加載的話萍虽,那么就會(huì)執(zhí)行createCallback這個(gè)回調(diào)Block,然后在createCallback里面開始構(gòu)建網(wǎng)絡(luò)請(qǐng)求,創(chuàng)建一個(gè) NSMutableURLRequest 對(duì)象和一個(gè) SDWebImageDownloaderOperation 對(duì)象形真,并將該 SDWebImageDownloaderOperation 對(duì)象添加到 SDWebImageDownloader 的downloadQueue 來啟動(dòng)異步下載任務(wù)杉编,在下載過程中執(zhí)行各類進(jìn)度Block回調(diào)。
f.當(dāng)圖片下載完成之后會(huì)回到done的Block回調(diào)中做圖片轉(zhuǎn)換處理和緩存操作咆霜。
g.回到UIImageView控件的設(shè)置圖片方法Block回調(diào)中邓馒,給對(duì)應(yīng)的UIImageView設(shè)置圖片,操作流程到此完成蛾坯。
3光酣、實(shí)現(xiàn)細(xì)節(jié)
SDWebImage 最核心的功能也就是以下 4 件事:
- 下載(SDWebImageDownloader)
- 緩存(SDImageCache)
- 將緩存和下載的功能組合起來(SDWebImageManager)
- 封裝成 UIImageView 等類的分類方法(UIImageView+WebCache 等)
3.1 SDWebImageDownloader
3.1.1 SDWebImageDownloader 繼承于 NSObject,主要承擔(dān)了異步下載圖片和優(yōu)化圖片加載的任務(wù)脉课。
SDWebImageDownloader 通過+initialize 和 -init 這兩個(gè)方法實(shí)現(xiàn)注冊(cè)通知和做一些初始化設(shè)置以及默認(rèn)設(shè)置挂疆。SDWebImageDownloader包括設(shè)置最大并發(fā)數(shù)(6)、下載超時(shí)時(shí)長(zhǎng)(15s)等下翎。
SDWebImageDownloader這個(gè)類里面除了這兩個(gè)方法缤言,最核心的方法就是downloadImageWithURL:options: progress: completed:方法,這個(gè)方法中首先調(diào)用 -addProgressCallback: andCompletedBlock: forURL: createCallback: 方法來保存每個(gè) url 對(duì)應(yīng)的回調(diào) block视事,-addProgressCallback 方法會(huì)先進(jìn)行錯(cuò)誤檢查胆萧,判斷 URL 是否為空,如果為 空, 則直接回調(diào) completedBlock跌穗,返回失敗的結(jié)果订晌,然后 return,否則將 URL 對(duì)應(yīng)的 progressBlock 和 completedBlock 保存到 URLCallbacks 屬性中去蚌吸。
有個(gè)細(xì)節(jié)要注意锈拨,因?yàn)榭赡芡瑫r(shí)下載多張圖片,所以就可能出現(xiàn)多個(gè)線程同時(shí)訪問 URLCallbacks 屬性的情況羹唠。為了保證線程安全奕枢,所以這里使用了 dispatch_barrier_sync 來分步執(zhí)行添加到 barrierQueue 中的任務(wù),這樣就能保證同一時(shí)間只有一個(gè)線程能對(duì) URLCallbacks 進(jìn)行操作佩微。
(dispatch_barrier_sync 將某個(gè)任務(wù)插入某個(gè)隊(duì)列中執(zhí)行:想了解的可以看看這篇文章 https://blog.csdn.net/u013046795/article/details/47057585)
如果這個(gè) URL 是第一次被下載缝彬,就要回調(diào) createCallback,createCallback 主要做的就是創(chuàng)建并開啟下載任務(wù)哺眯,下面是 createCallback 的具體實(shí)現(xiàn)邏輯:
1.創(chuàng)建一個(gè) NSMutableURLRequest 對(duì)象和一個(gè) SDWebImageDownloaderOperation 對(duì)象谷浅,并將該 SDWebImageDownloaderOperation 對(duì)象添加到 SDWebImageDownloader 的downloadQueue 來啟動(dòng)異步下載任務(wù)。
2.SDWebImageDownloaderOperation 中有3個(gè)block回調(diào)奶卓,分別是progressBlock(接收到的數(shù)據(jù)大小和預(yù)計(jì)數(shù)據(jù)大小)一疯,completedBlock(圖片 UIImage,圖片數(shù)據(jù) NSData夺姑,錯(cuò)誤 NSError墩邀,是否結(jié)束 isFinished),cancelBlock(移除 url 對(duì)應(yīng)的所有回調(diào) block)瑟幕;這三個(gè)block都用了weak-strong dance磕蒲,使用 strongSelf 強(qiáng)引用 weakSelf,目的是為了保住 self 不被釋放只盹,然后檢查 self 是否已經(jīng)被釋放(這里為什么先“崩蓖活”后“判空”呢?因?yàn)槿绻扰锌盏脑捴潮埃锌赡芘锌蘸?self 就被釋放了)
(對(duì)weak-strong dance不理解可以看看 http://www.reibang.com/p/4e6153ea2734)
- 設(shè)置下載完成后是否需要解壓縮
- 如果設(shè)置了 username 和 password站削,就給 operation 的下載請(qǐng)求設(shè)置一個(gè) NSURLCredential 身份認(rèn)證
- 設(shè)置 operation 的隊(duì)列優(yōu)先級(jí)
- 將 operation 加入到隊(duì)列 downloadQueue 中,隊(duì)列(NSOperationQueue)會(huì)自動(dòng)管理 operation 的執(zhí)行
- 如果 operation 執(zhí)行順序是先進(jìn)后出孵稽,就設(shè)置 operation 依賴關(guān)系(先加入的依賴于后加入的)绳矩,并記錄最后一個(gè) operation(lastAddedOperation)
3.1.2 SDWebImageDownloaderOperation
當(dāng)創(chuàng)建的 SDWebImageDownloaderOperation 對(duì)象被加入到 downloader 的 downloadQueue 中時(shí)碱璃,該對(duì)象的 -start 方法就會(huì)被自動(dòng)調(diào)用转捕。
-start 方法中首先創(chuàng)建了用來下載圖片數(shù)據(jù)的 NSURLSession胳螟,然后開啟 connection,同時(shí)發(fā)出開始圖片下載的 SDWebImageDownloadStartNotification 通知接校,為了防止非主線程的請(qǐng)求被 kill 掉猛频,這里開啟 runloop 保活,直到請(qǐng)求返回鹿寻。
一張圖片的數(shù)據(jù)下載是由一個(gè) NSConnection 對(duì)象來完成的睦柴,這個(gè)對(duì)象的整個(gè)生命周期(從創(chuàng)建到下載結(jié)束)又是由 SDWebImageDownloaderOperation 來控制的,將 operation 加入到 operation queue 中就可以實(shí)現(xiàn)多張圖片同時(shí)下載了毡熏。
簡(jiǎn)單概括成一句話就是坦敌,NSURLSession 負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求,NSOperation 負(fù)責(zé)多線程痢法。
(為什么要用runloop :https://blog.ibireme.com/2015/05/18/runloop/)
3.2 SDImageCache
3.2.1 SDImageCache 管理著一個(gè)內(nèi)存緩存和磁盤緩存(可選)狱窘,同時(shí)在寫入磁盤緩存時(shí)采取異步執(zhí)行,所以不會(huì)阻塞主線程疯暑,影響用戶體驗(yàn)。為什么需要緩存膘滨?
- 以空間換時(shí)間铲咨,提升用戶體驗(yàn):加載同一張圖片,讀取緩存是肯定比遠(yuǎn)程下載的速度要快得多的
- 減少不必要的網(wǎng)絡(luò)請(qǐng)求,提升性能,節(jié)省流量:一般來講,同一張圖片的 URL 是不會(huì)經(jīng)常變化的,所以沒有必要重復(fù)下載统扳。另外倾鲫,現(xiàn)在的手機(jī)存儲(chǔ)空間都比較大磕道,相對(duì)于流量來疯特,緩存占的那點(diǎn)空間算不了什么。
3.2.2 SDImageCache 的內(nèi)存緩存是通過一個(gè)繼承 NSCache 的 AutoPurgeCache 類來實(shí)現(xiàn)的,NSCache 是一個(gè)類似于 NSMutableDictionary 存儲(chǔ) key-value 的容器腾誉,主要有以下幾個(gè)特點(diǎn):
- 自動(dòng)刪除機(jī)制:當(dāng)系統(tǒng)內(nèi)存緊張時(shí)徘层,NSCache會(huì)自動(dòng)刪除一些緩存對(duì)象
- 線程安全:從不同線程中對(duì)同一個(gè) NSCache 對(duì)象進(jìn)行增刪改查時(shí)峻呕,不需要加鎖
- 不同于 NSMutableDictionary,NSCache存儲(chǔ)對(duì)象時(shí)不會(huì)對(duì) key 進(jìn)行 copy 操作
3.2.3 SDImageCache 的磁盤緩存是通過異步操作 NSFileManager 存儲(chǔ)緩存文件到沙盒來實(shí)現(xiàn)的趣效。
3.2.4 磁盤清理
(1).清掃磁盤緩存(clean)和清空磁盤緩存(clear)是兩個(gè)不同的概念瘦癌,清空是刪除整個(gè)緩存目錄,清掃只是刪除部分緩存文件跷敬。
(2).清掃磁盤緩存有兩個(gè)指標(biāo):一是緩存有效期讯私,二是緩存體積最大限制。SDImageCache中的緩存有效期是通過 maxCacheAge 屬性來設(shè)置的西傀,默認(rèn)值是 1 周斤寇,緩存體積最大限制是通過 maxCacheSize 來設(shè)置的,默認(rèn)值為 0拥褂。
一般在應(yīng)用即將終止時(shí)和退到后臺(tái)時(shí)娘锁,都會(huì)調(diào)用 -cleanDiskWithCompletionBlock: 方法來異步清掃緩存,清掃磁盤緩存的邏輯是饺鹃,先遍歷所有緩存文件莫秆,并根據(jù)文件的修改時(shí)間來刪除過期的文件,同時(shí)記錄剩下的文件的屬性和總體積大小尤慰,如果設(shè)置了 maxCacheAge 屬性的話馏锡,接下來就把剩下的文件按修改時(shí)間從小到大排序(最早的排最前面)雷蹂,最后再遍歷這個(gè)文件數(shù)組伟端,一個(gè)一個(gè)刪,直到總體積小于 desiredCacheSize 為止匪煌,也就是 maxCacheSize 的一半责蝠。
(3).清理內(nèi)存緩存,一般在系統(tǒng)拋出內(nèi)存警告的時(shí)候萎庭,SDWebImage會(huì)自動(dòng)調(diào)用清除內(nèi)存緩存方法霜医,等系統(tǒng)拋出內(nèi)存警告可能有點(diǎn)困難,所以可以根據(jù)需求驳规,自己調(diào)用[[SDImageCache sharedImageCache] clearMemory]; 肴敛,不過這個(gè)方法只是清除了SDWebImage的緩存,并沒有清除系統(tǒng)緩存吗购。如果需要清楚系統(tǒng)緩存可以調(diào)用
[[NSURLCache sharedURLCache] removeAllCachedResponses];來實(shí)現(xiàn)医男。
3.3 SDWebImageManager
SDWebImageManager是圖片加載管理器,主要是將下載和緩存兩個(gè)功能結(jié)合起來捻勉,才算是一個(gè)完整的圖片加載器镀梭。
SDWebImageManager 的核心任務(wù)是由 -downloadImageWithURL:options:progress:completed: 方法來實(shí)現(xiàn)的,這個(gè)方法中先會(huì)從 SDImageCache 中讀取緩存踱启,如果有緩存报账,就直接返回緩存研底,如果沒有就通過 SDWebImageDownloader 去下載,下載成功后再保存到緩存中去透罢,然后再回調(diào) completedBlock榜晦。其中 progressBlock 的回調(diào)是直接交給了 SDWebImageDownloader 的 progressBlock 來處理的。
SDWebImageManager 在讀取緩存和下載之前會(huì)創(chuàng)建一個(gè) SDWebImageCombinedOperation 對(duì)象羽圃,這個(gè)對(duì)象是用來管理緩存讀取操作和下載操作的芽隆,SDWebImageCombinedOperation 對(duì)象有 3 個(gè)屬性:
- cancelled:用來取消當(dāng)前加載任務(wù)的
- cancelBlock:用來移除當(dāng)前加載任務(wù)和取消下載任務(wù)的
- cacheOperation:用來取消讀取緩存操作
3.4 UIImageView+WebCache
UIImageView+WebCache就是我們平時(shí)最常用的圖片加載,是通過調(diào)用 UIImageView+WebCache 的 -sd_setImageWithURL:... 系列方法來加載的统屈,UIImageView+WebCache 實(shí)際上是將 SDWebImageManager 封裝了一層胚吁,內(nèi)部針對(duì) UIImageView 做了一些處理,使用起來更方便愁憔、更直接腕扶、更簡(jiǎn)單。
UIImageView+WebCache 的核心邏輯都在 - sd_setImageWithURL:placeholderImage:options:progress:completed: 方法中吨掌,為了防止多個(gè)異步加載任務(wù)同時(shí)存在時(shí)半抱,可能出現(xiàn)互相沖突和干擾,該方法中首先通過調(diào)用 -sd_cancelCurrentImageLoad 方法取消這個(gè) UIImageView 當(dāng)前的下載任務(wù)膜宋,然后設(shè)置了占位圖窿侈,如果 url 不為 nil,接著就調(diào)用 SDWebImageManager 的 -downloadImage... 方法開始加載圖片秋茫,并將這個(gè)加載任務(wù) operation 保存起來史简,用于后面的 cancel 操作。圖片獲取成功后肛著,再重新設(shè)置 imageView 的 image圆兵,并回調(diào) completedBlock。
需要注意的是為了防止多個(gè)異步加載任務(wù)同時(shí)存在時(shí)枢贿,可能出現(xiàn)互相沖突和干擾殉农,每個(gè) UIImageView 的圖片加載任務(wù)都會(huì)保存成一個(gè) Associated Object,方便需要時(shí)取消任務(wù)局荚。這個(gè) Associated Object 的操作是在 UIView+WebCacheOperation 中實(shí)現(xiàn)的超凳,因?yàn)槌?UIImageView 用到圖片加載功能之外,還有 UIButton 等其他類也用到了加載遠(yuǎn)程圖片的功能耀态,所以需要進(jìn)行同樣的處理轮傍,這樣設(shè)計(jì)實(shí)現(xiàn)了代碼的復(fù)用。
四茫陆、遇到的問題
- 問題 1:使用SDWebImage加載較多圖片時(shí)金麸,會(huì)出現(xiàn)內(nèi)存警告;
解決方案:定期調(diào)用 [[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"]; - 問題 2:圖片刷新問題:SDWebImage 在進(jìn)行緩存時(shí)忽略了所有服務(wù)器返回的 caching control 設(shè)置簿盅,并且在緩存時(shí)沒有做時(shí)間限制挥下,這也就意味著圖片 URL 必須是靜態(tài)的了揍魂,要求服務(wù)器上一個(gè) URL 對(duì)應(yīng)的圖片內(nèi)容不允許更新。但是如果存儲(chǔ)圖片的服務(wù)器不由自己控制棚瘟,也就是說 圖片內(nèi)容更新了现斋,URL 卻沒有更新,這種情況怎么辦偎蘸?
解決方案:在調(diào)用 sd_setImageWithURL: placeholderImage: options:方法時(shí)設(shè)置 options 參數(shù)為SDWebImageRefreshCached庄蹋,這樣雖然會(huì)降低性能,但是下載圖片時(shí)會(huì)照顧到服務(wù)器返回的 caching control迷雪。 - 問題 3:在加載圖片時(shí)限书,如何添加默認(rèn)的 progress indicator ?
解決方案:在調(diào)用 -sd_setImageWithURL:方法之前章咧,先調(diào)用下面的方法:
[imageView sd_setShowActivityIndicatorView:YES];
[imageView sd_setIndicatorStyle:UIActivityIndicatorViewStyleGray];
五倦西、總結(jié)
SDWebImage作為一個(gè)優(yōu)秀的圖片加載框架,提供的使用方法和接口對(duì)開發(fā)者來說非常友好赁严。
其內(nèi)部實(shí)現(xiàn)多是采用Block的方式來實(shí)現(xiàn)回調(diào)扰柠,代碼閱讀起來可能沒有那么直觀。
內(nèi)部有用到了很多好的技術(shù)疼约,比如卤档,GCD,線程加鎖等程剥,可供我們學(xué)習(xí)劝枣。
SDWebImage中有兩個(gè)比較好用的宏定義定義之dispatch_main_sync_safe和dispatch_main_async_safe。
define dispatch_main_sync_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_sync(dispatch_get_main_queue(), block);\
}
define dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
SDWebImage頻繁運(yùn)用了runtime中的關(guān)聯(lián)函數(shù)倡缠,用關(guān)聯(lián)函數(shù)關(guān)聯(lián)一個(gè)對(duì)象哨免,稱關(guān)聯(lián)對(duì)象,關(guān)聯(lián)對(duì)象相當(dāng)于實(shí)例變量昙沦,在類別里面,不能創(chuàng)建實(shí)例變量载荔,關(guān)聯(lián)對(duì)象就可以解決這種問題盾饮。
主要函數(shù)有:
objc_setAssociatedObject 相當(dāng)于 setValue:forKey 進(jìn)行關(guān)聯(lián)value對(duì)象
objc_getAssociatedObject 用來讀取對(duì)象
objc_AssociationPolicy 屬性 是設(shè)定該value在object內(nèi)的屬性,即 assgin, (retain,nonatomic)...等
objc_removeAssociatedObjects 函數(shù)來移除一個(gè)關(guān)聯(lián)對(duì)象懒熙,或者使用objc_setAssociatedObject函數(shù)將key指定的關(guān)聯(lián)對(duì)象設(shè)置為nil丘损。
相關(guān)參數(shù):
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
id object :表示關(guān)聯(lián)者,是一個(gè)對(duì)象工扎,變量名理所當(dāng)然也是object
const void *key :獲取被關(guān)聯(lián)者的索引key
id value :被關(guān)聯(lián)者徘钥,這里是一個(gè)block
objc_AssociationPolicy policy : 關(guān)聯(lián)時(shí)采用的協(xié)議,有assign肢娘,retain呈础,copy等協(xié)議舆驶,一般使 用OBJC_ASSOCIATION_RETAIN_NONATOMIC。
相關(guān)協(xié)議:
OBJC_ASSOCIATION_ASSIGN 等價(jià)于 @property(assign)而钞。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等價(jià)于 @property(strong, nonatomic)沙廉。
OBJC_ASSOCIATION_COPY_NONATOMIC等價(jià)于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN等價(jià)于@property(strong,atomic)臼节。
OBJC_ASSOCIATION_COPY等價(jià)于@property(copy, atomic)撬陵。
六、SDWebImage3.8.2與4.0的區(qū)別
SDWebImage4.0是一個(gè)大版本网缝,在結(jié)構(gòu)上和API方面都有所改動(dòng)巨税。
區(qū)別:
1、新增targetURL粉臊,存放原始圖像url垢夹;
2、新增一個(gè)FLAnimatedImageView+WebCache類维费,主要在動(dòng)圖支持上做了改進(jìn)果元,尤其是 GIF;
3犀盟、SDWebImage4.0新增一個(gè)UIView+WebCache類中而晒,將UIImageView+WebCache類中的方法移動(dòng)到UIView+WebCache類中,UIImageView對(duì)象依然響應(yīng)這些方法阅畴。
SDWebImage4.0新增了很多方法倡怎,詳細(xì)的在GitHub上看官方文檔。
https://github.com/rs/SDWebImage/blob/master/Docs/SDWebImage-4.0-Migration-guide.md