YYWebImage 學(xué)習(xí)(一)

最近回頭一看猿规,發(fā)現(xiàn)我們的項目現(xiàn)在對圖片處理都是用YYWebImage 的處理方式方式的,用了不短時間了买喧,卻沒有好好了解下,今天特此學(xué)習(xí)下箩朴。首先然而怎么下手呢岗喉?如何提高閱讀源代碼的能力?結(jié)合自己炸庞,決定在第一篇钱床,帶著一個問題,去簡單了解埠居。

問題:為什么使用下面這個方法去獲取圖片查牌?

- (void)yy_setImageWithURL:(NSURL *)imageURL
               placeholder:(UIImage *)placeholder
                   options:(YYWebImageOptions)options
                  progress:(YYWebImageProgressBlock)progress
                 transform:(YYWebImageTransformBlock)transform
                completion:(YYWebImageCompletionBlock)completion

先簡單了解下這幾個參數(shù)的含義

* imageURL:圖片的URL
* placeholder: 備用圖片
* options: YYWebImageOptions(圖片下載時同時的操作,可以仔細看一下,很強大的
(展示進度滥壕,緩存方式纸颜,HTPPS的處理,忽略其他绎橘,失敗時處理等等))
* progress: 圖片下載的進度(receivedSize/expectedSize)
* transform: 對圖片是否需要處理(大小胁孙、圓角之類的添加),為更適應(yīng)圖片的展示
* completion:完成后称鳞,可以了解的信息(url,from,error)

然后進入去看一下詳細的實現(xiàn)

1涮较、圍繞著_YYWebImageSetter進行一系列的判斷。
2冈止、異步中到 YYWebImageManager 的網(wǎng)絡(luò)處理
3狂票、同時對 operation 進行處理,在YYWebImageOperation(NSOperation的子類)中熙暴。

所以闺属,得先對:YYWebImageManager慌盯、YYWebImageOperation 有個大致了解。

YYWebImageManager

用來創(chuàng)建和管理網(wǎng)絡(luò)圖片任務(wù)的管理器,這個類其實就一個作用,管理生成一個YYWebImageOperation實例

第一掂器,我們從其三個枚舉就可以大致了解它一些東西啦

* YYWebImageOptions //控制圖片請求的模式
* YYWebImageFromType //用來告訴我們圖片來源
* YYWebImageStage //用來告訴我們圖片下載的完成度的

第二亚皂,再看看其幾個 Block

* YYWebImageProgressBlock  //從遠程下載完成過程的回調(diào)
* YYWebImageTransformBlock //  圖片從遠程下載完成之前會執(zhí)行這個block,用來執(zhí)行一些額外的操作
* YYWebImageCompletionBlock //在當(dāng)圖片下載完成或者取消的時候調(diào)用

第三,看看它的初始化和屬性唉匾,有很多孕讳,選擇一個最重要的。也就是將上述 枚舉和 block 結(jié)合的體現(xiàn)巍膘。

- (YYWebImageOperation *)requestImageWithURL:(NSURL *)url 
                                     options:(YYWebImageOptions)options 
                                    progress:(YYWebImageProgressBlock)progress 
                                   transform:(YYWebImageTransformBlock)transform 
                                  completion:(YYWebImageCompletionBlock)completion;

第四,看這個初始化的實現(xiàn)

- (YYWebImageOperation *)requestImageWithURL:(NSURL *)url
                                     options:(YYWebImageOptions)options
                                    progress:(YYWebImageProgressBlock)progress
                                   transform:(YYWebImageTransformBlock)transform
                                  completion:(YYWebImageCompletionBlock)completion {
    
   //設(shè)置request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.timeoutInterval = _timeout;
    request.HTTPShouldHandleCookies = (options & YYWebImageOptionHandleCookies) != 0;
    request.allHTTPHeaderFields = [self headersForURL:url];
    request.HTTPShouldUsePipelining = YES;
    // 設(shè)置緩存方式
    request.cachePolicy = (options & YYWebImageOptionUseNSURLCache) ?
        NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
    // 生成一個我們需要的YYWebImageOperation對象
    YYWebImageOperation *operation = [[YYWebImageOperation alloc] initWithRequest:request
                                                                          options:options
                                                                            cache:_cache
                                                                         cacheKey:[self cacheKeyForURL:url]
                                                                         progress:progress
                                                                        transform:transform ? transform : _sharedTransformBlock
                                                                       completion:completion];
    // 如果有用戶名跟密碼,生成系統(tǒng)提供的NSURLCredential
    if (_username && _password) {
        operation.credential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceForSession];
    }
    // 真正開始操作
    if (operation) {
        NSOperationQueue *queue = _queue;
        if (queue) {
            [queue addOperation:operation];
        } else {
            [operation start];
        }
    }
    return operation;
}

注意 request 各個屬性的設(shè)置芋簿,特別是緩存策略峡懈,后期可以再了解 YYCache,以及NSURLCredential的身份認(rèn)證与斤。

YYWebImageOperation

YYWebImageOperation 類是NSOperation的子類,用來通過請求獲取圖片肪康。

第一,對operation中一些狀態(tài)進行正確的處理

- (void)_finish 
- (void)_startOperation
- (void)_startRequest:(id)object
- (void)_cancelOperation

第二撩穿,通過不同的方式下載得到圖片進行的處理

//從磁盤緩存中接受圖片
- (void)_didReceiveImageFromDiskCache:(UIImage *)image
// 從網(wǎng)絡(luò)下載的圖片
- (void)_didReceiveImageFromWeb:(UIImage *)image

第三磷支,看NSURLColleciton 的代理方法


//即將緩存請求結(jié)果
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
//請求已經(jīng)收到相應(yīng)
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
//收到數(shù)據(jù)回調(diào)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
//連接已經(jīng)結(jié)束加載
- (void)connectionDidFinishLoading:(NSURLConnection *)connection

第四,真正重寫的NSOperation的方法食寡,進行處理

- (void)start
- (void)cancel

在此我們可以大致了解作者在對管理下載隊列的時候的想法,以及自定義一個operation時的大致想法雾狈。

總的說來,這一篇只是大致的思路抵皱,要去看詳細源碼善榛,注意里面一些細節(jié)的才是重點,第二篇筆記重點來挖掘細節(jié)呻畸。


額外問題的發(fā)現(xiàn)
1移盆、static 內(nèi)聯(lián)函數(shù)的使用 ?
static inline void _yy_dispatch_sync_on_main_queue(void (^block)()) {
    if (pthread_main_np()) {
        block();
    } else {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

簡單理解伤为, 宏一樣的函數(shù)咒循,方便使用。深入理解C語言的define和內(nèi)聯(lián)函數(shù)
另外也可了解下iOS OC內(nèi)聯(lián)函數(shù) inline绞愚。

  • static 標(biāo)識此內(nèi)聯(lián)聯(lián)函數(shù)只能在本文件中使用叙甸,限制了內(nèi)聯(lián)函數(shù)的作用域。
  • 相對于宏來說爽醋,static inline具有和宏同樣級別的開銷蚁署,而且還提供了類型安全,沒有長度和格式的具體限制蚂四。

Ps: static 函數(shù)的用法

static void URLBlacklistInit() {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        URLBlacklist = [NSMutableSet new];
        URLBlacklistLock = dispatch_semaphore_create(1);
    });
}

用 static 這樣表示該函數(shù)聲明為內(nèi)部函數(shù)(又叫靜態(tài)函數(shù))光戈,這樣該函數(shù)就只能在其定義所在的文件中使用哪痰。如果在不同的文件中有同名的內(nèi)部函數(shù),則互不干擾久妆。

2晌杰、類名和函數(shù)名 前面加下劃線的運用 ?
@interface _YYWebImageSetter : NSObject
+ (void)_delaySetActivity:(NSTimer *)timer
- (void)_startOperation

一般是我們是用前綴避免命名空間沖突,如 yy_setImageURL:之類的筷弦,但是加上下劃線有時個什么情況呢肋演?

而且蘋果公司喜歡單用一個下劃線作為私有的前綴。此時如果我們也這樣想烂琴,假如蘋果公司提供的某個類中繼承了某一個子類爹殊,那我們在子類里可能會無意間覆寫了父類的同名方法,因此官方推薦是不要但寫一個下劃線做私有方法的前綴奸绷。

作者為什么這么寫呢梗夸,對于部分變量名,類名還好理解号醉,但是對私有方法的處理反症,可以仔細看看。

3畔派、objc_getAssociatedObject大量的使用

這個就是為了解決在分類中添加實例變量的快速方法啦铅碍。Objective-C Associated Objects 的實現(xiàn)原理

4、@implementation 后直接使用成員變量?
@implementation User : NSObject {
    NSString *_name;
}

以前沒有這樣使用過线椰,但是是合法的哦胞谈。對比@interface和@implementation

5、自旋鎖 & 遞歸鎖

OSSpinLock(自旋鎖),自旋鎖在保證了多線程同時訪問本類的時候不會導(dǎo)致數(shù)據(jù)出錯的同時性能高效士嚎。
NSRecursiveLock(遞歸鎖),遞歸鎖防止死鎖,因為請求可能是有多個的呜魄。

使用案例

static OSSpinLock URLBlacklistLock;//黑名單鎖
/**
 *  把url添加進黑名單
 */
static void URLInBlackListAdd(NSURL *url) {
    if (!url || url == (id)[NSNull null]) return;
    URLBlacklistInit();
    OSSpinLockLock(&URLBlacklistLock);
    [URLBlacklist addObject:url];
    OSSpinLockUnlock(&URLBlacklistLock);
}
@property (nonatomic, strong) NSRecursiveLock *lock; //遞歸鎖
- (void)dealloc {
    [_lock lock];
    // 
    [_lock unlock];
}

了解更多的鎖的信息,可以看看這篇結(jié)合 thread 講的 -----Thread基礎(chǔ)知識

備注參考:

https://github.com/ibireme/YYWebImage

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莱衩,一起剝皮案震驚了整個濱河市爵嗅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笨蚁,老刑警劉巖睹晒,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異括细,居然都是意外死亡伪很,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門奋单,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锉试,“玉大人,你說我怎么就攤上這事览濒〈舾牵” “怎么了拖云?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長应又。 經(jīng)常有香客問我宙项,道長,這世上最難降的妖魔是什么株扛? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任尤筐,我火速辦了婚禮,結(jié)果婚禮上洞就,老公的妹妹穿的比我還像新娘盆繁。我一直安慰自己,他們只是感情好旬蟋,可當(dāng)我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布改基。 她就那樣靜靜地躺著,像睡著了一般咖为。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稠腊,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天躁染,我揣著相機與錄音,去河邊找鬼架忌。 笑死吞彤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叹放。 我是一名探鬼主播饰恕,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼井仰!你這毒婦竟也來了埋嵌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤俱恶,失蹤者是張志新(化名)和其女友劉穎雹嗦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體合是,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡了罪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了聪全。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泊藕。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖难礼,靈堂內(nèi)的尸體忽然破棺而出娃圆,到底是詐尸還是另有隱情玫锋,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布踊餐,位于F島的核電站景醇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吝岭。R本人自食惡果不足惜三痰,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窜管。 院中可真熱鬧散劫,春花似錦、人聲如沸幕帆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽失乾。三九已至常熙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碱茁,已是汗流浹背裸卫。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纽竣,地道東北人墓贿。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像蜓氨,于是被迫代替她去往敵國和親聋袋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容