SDWebImage 源碼解讀之視圖類的WebCache

本章開始將介紹SDWebImage庫中加載網絡圖片的視圖類的拓展悉患,這也是SDWebImage庫將底層的緩存功能,加載功能封裝后在UI層進行展示的結合业扒,涉及到的視圖類有UIView叮称,UIImageView,UIButton笑窜,涉及到SDWebImage庫中的文件則有UIView+WebCacheOperation致燥,UIImageView+WebCache,UIImageView+HighlightedWebCache排截,UIButton+WebCache嫌蚤。首先解釋一下涉及到的一些基本概念和方法:

?OC中的關聯(lián)機制

在OC中,關聯(lián)是指通過某種方式把兩個互不聯(lián)系的對象相互關聯(lián)起來断傲,使得其中的一個對象作為另外一個對象的一部分脱吱。我們知道,在 OC中可以通過 Category 給一個現有的類添加屬性认罩,但是卻不能添加實例變量箱蝠,這似乎成為了OC 的一個明顯短板。然而值得慶幸的是,我們可以通過 Associated Objects 來彌補這一不足宦搬。

?關聯(lián)涉及的方法跟使用

與 Associated Objects 相關的函數主要有三個牙瓢,分別是:

objc_setAssociatedObject 用于給對象添加關聯(lián)對象,傳入 nil 則可以移除已有的關聯(lián)對象床三,它需要四個參數:源對象一罩,關鍵字,關聯(lián)的對象和一個關聯(lián)策略撇簿。例如:

NSString *message = @"你是誰";

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"我要傳值·" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil];

alert.delegate = self;

[alert show];

objc_setAssociatedObject(alert, @"msgstr", message,OBJC_ASSOCIATION_ASSIGN);

這樣就把alert和message字符串關聯(lián)起來聂渊,作為alertview的一部分,關鍵詞就是msgstr四瘫,之后可以使用objc_getAssociatedObject從alertview中獲取到所關聯(lián)的對象汉嗽,便可以訪問messag了

objc_getAssociatedObject 用于獲取關聯(lián)對象,以上面代碼為例:

//通過 objc_getAssociatedObject獲取關聯(lián)對象

NSString? *messageString = objc_getAssociatedObject(alertView, @"msgstr");

objc_removeAssociatedObjects 用于移除一個對象的所有關聯(lián)對象找蜜。

注:objc_removeAssociatedObjects 函數我們一般是用不上的饼暑,因為這個函數會移除一個對象的所有關聯(lián)對象,將該對象恢復成“原始”狀態(tài)洗做。這樣做就很有可能把別人添加的關聯(lián)對象也一并移除弓叛,這并不是我們所希望的。所以一般的做法是通過給 objc_setAssociatedObject 函數傳入 nil 來移除某個已有的關聯(lián)對象诚纸。

?關聯(lián)策略

在給一個對象添加關聯(lián)對象時有五種關聯(lián)策略可供選擇:

關聯(lián)對象的五種關聯(lián)策略與屬性的限定符非常類似撰筷,在絕大多數情況下,我們都會使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC 的關聯(lián)策略畦徘,這可以保證我們持有關聯(lián)對象毕籽。

下面開始對SDWebImage庫涉及的類進行解讀

一.SDWebImage 源碼解讀之UIView+WebCacheOperation

下面貼上這個文件的代碼方法:

從方法名上可以很明確的知道了作者在這個類想做的事情,給需要進行圖片加載操作的UIView通過鍵值對的方式實現圖片加載操作的取消跟移除井辆,至于是通過什么樣的方式关筒,看了源代碼之后我們就能知道,是通過上面介紹的關聯(lián)機制的方式杯缺,接下來看看代碼的具體實現:

在第一個方法中可以知道蒸播,SDWebImage庫會為每一個使用其圖片加載功能的UIView對象通過關聯(lián)機制關聯(lián)了一個操作字典集合,在圖片的整個加載過程中萍肆,凡是需要給對象增加關聯(lián)屬性的袍榆,都會以鍵值對的方式保存在該字典集里,同時匾鸥,所有的操作都會保持一致性跟唯一性,這個可以從后面的兩個方法看出碉纳,不管是進行設置操作勿负,還是進行取消操作,SDWebImage庫都會對operationDictionary進行遍歷操作,找出已經保存在該集合中的對應屬性值并進行移除操作奴愉。

二.SDWebImage 源碼解讀之UIImageView+WebCache

在該類中琅摩,提供給UIImageView根據不同場景去加載URL的方法比較多,大同小異锭硼,但是所有的加載URL的方法都是基于一個方法房资,所以下面將會著重去講解這個方法的實現:

下面來看看這個方法的實現:

在該方法實現的開頭部分,也是利用了關聯(lián)機制檀头,為每一個UIImageView對象關聯(lián)了一個圖片的URL轰异,使得每一個對象都會有一個明確的圖片路徑,在圖片加載過程中暑始,SDWebImage提供了多種圖片獲取方式的可選參數(SDWebImageOptions)options搭独,分別有:

* SDWebImageRetryFailed = 1<< 0,? ? 默認選項,失敗后重試

* SDWebImageLowPriority = 1<< 1, ? ?UI交互期間開始下載廊镜,導致延遲下載比如UIScrollView減速

* SDWebImageCacheMemoryOnly = 1<< 2,? ? 只進行內存緩存

* SDWebImageProgressiveDownload = 1<< 3, ?漸進式下載,顯示的圖像是逐步在下載

* SDWebImageRefreshCached = 1<< 4,? ? 刷新緩存

* SDWebImageContinueInBackground =1 << 5,? ? 后臺繼續(xù)下載圖像

* SDWebImageHandleCookies = 1<< 6,? ? 處理 Cookie

* SDWebImageAllowInvalidSSLCertificates= 1 << 7,? ? 允許無效的 SSL 驗證

* SDWebImageHighPriority = 1<< 8, ? ? ?優(yōu)先下載

* SDWebImageDelayPlaceholder = 1<< 9? ? ? 延遲顯示占位圖片

* SDWebImageTransformAnimatedImage = 1 << 10? ? ? 改變動畫形象

? ? ? ? 在使用過程中牙肝,我們可以根據自己的業(yè)務需要,設置符合場景的值嗤朴,通常情況下配椭,都是選擇默認的設置,而在代碼的實現過程中雹姊,會對options的值跟SDWebImageDelayPlaceholder進行位運算股缸,以此來判斷是否在圖片未下載前進行占位圖片的設置,而這種設置會保證是在線程安全的主線程進行容为,以便能夠及時的刷新界面顯示乓序。

? ? ? ? 接下來,代碼會對圖片的URL進行判斷坎背,如果URL為空的情況下替劈,SDWebImage庫會返回一個默認的錯誤信息給用戶,以便用戶進行查找得滤,而不會進行網絡加載操作陨献,若不為空的情況下,則會使用SDWebImage庫的核心功能懂更,圖片下載操作眨业,對圖片進行網絡下載,并返回一個網絡加載操作對象沮协,保存在對象的操作字典集中(SDWebImage庫的網絡加載層之后會專門講解龄捡,不在這里進行描述),圖片下載操作的最終結果將會回調到安全的主線程中去刷新界面慷暂。

? ? ? ? 在進行界面刷新操作前聘殖,除了進行必要的操作外,作者還進行了一種情況下的判斷,網絡請求本身就是一種異步執(zhí)行的操作奸腺,不會影響到用戶的行為操作餐禁,如果在網絡回調執(zhí)行時,對象本身就已經被銷毀了突照,這時再進行對象的刷新操作帮非,這種行為是不安全的,所以作者才在進行刷新操作前進行判斷對象是否銷毀操作讹蘑,這個是必須的末盔,也是我們在開發(fā)中需要進行考慮的。

? ? ?這個類中還有一個方法值得一提衔肢,代碼如下:

? ? ?該方法的實現思想與SDWebImage庫的緩存策略有一定的關系(SDWebImage庫的緩存策略的緩存策略之后會講到庄岖,不在這里進行描述),該方法會先從本地的緩存數據中去查找是否已經加載過該圖片角骤,如果加載過該圖片就會將緩存的圖片當做占位圖片刷新到對象中隅忿,同時在對圖片進行一次網絡刷新處理,保證圖片數據的實時性邦尊。

二.SDWebImage 源碼解讀之UIButton+WebCache背桐,UIImageView+HighlightedWebCache

這兩個文件實現加載網絡圖片的方式跟UIImageView+WebCache類似,其實現思路大同小異蝉揍。

總結:關聯(lián)機制的使用链峭,使得SDWebImage庫在給對象增加屬性時提供了大大的方便性,既減少代碼之間的引用關系又沾,也使得對象之間的聯(lián)系更直接弊仪。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市杖刷,隨后出現的幾起案子励饵,更是在濱河造成了極大的恐慌,老刑警劉巖滑燃,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件役听,死亡現場離奇詭異,居然都是意外死亡表窘,警方通過查閱死者的電腦和手機典予,發(fā)現死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乐严,“玉大人瘤袖,你說我怎么就攤上這事“貉椋” “怎么了捂敌?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵昭娩,是天一觀的道長。 經常有香客問我黍匾,道長,這世上最難降的妖魔是什么呛梆? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任锐涯,我火速辦了婚禮,結果婚禮上填物,老公的妹妹穿的比我還像新娘纹腌。我一直安慰自己,他們只是感情好滞磺,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布升薯。 她就那樣靜靜地躺著,像睡著了一般击困。 火紅的嫁衣襯著肌膚如雪涎劈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天阅茶,我揣著相機與錄音蛛枚,去河邊找鬼。 笑死脸哀,一個胖子當著我的面吹牛蹦浦,可吹牛的內容都是我干的。 我是一名探鬼主播撞蜂,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盲镶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝌诡?” 一聲冷哼從身側響起溉贿,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎送漠,沒想到半個月后顽照,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡闽寡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年代兵,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爷狈。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡植影,死狀恐怖,靈堂內的尸體忽然破棺而出涎永,到底是詐尸還是另有隱情思币,我是刑警寧澤鹿响,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站谷饿,受9級特大地震影響惶我,放射性物質發(fā)生泄漏。R本人自食惡果不足惜博投,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一绸贡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毅哗,春花似錦听怕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至翅睛,卻和暖如春声搁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捕发。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工酥艳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爬骤。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓充石,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霞玄。 傳聞我的和親對象是個殘疾皇子骤铃,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容