本章開始將介紹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類似,其實現思路大同小異蝉揍。