SDWebImage源碼解讀(三) SDWebImageCompat

前言
本篇主要解讀SDWebImage的配置文件。正如compat的定義,該配置文件主要是兼容Apple的其他設備。也許我們真實的開發平臺只有一個,但考慮各個平臺的兼容性,對于框架有著很重要的意義。這篇文章的重點是抽取出對于iOS很重要的用法,能夠在項目開發中提高效率。

import

導入這個頭文件,我們就能訪問系統提供的配置選項了,我們接下來會對該文件出現的配置屬性做出解釋。

OBJC_GC

ifdef OBJC_GC

#error SDWebImage does not support Objective-C Garbage Collection

endif

SDWebImage不支持垃圾回收機制,垃圾回收(Gargage-collection)是Objective-c提供的一種自動內存回收機制。在iPad/iPhone環境中不支持垃圾回收功能。
當啟動這個功能后,所有的retain,autorelease,release和dealloc方法都將被系統忽略。

SD_MAC
// Apple's defines from TargetConditionals.h are a bit weird.
// Seems like TARGET_OS_MAC is always defined (on all platforms).
// To determine if we are running on OSX, we can only relly on TARGET_OS_IPHONE=0 and all the other platforms

if !TARGET_OS_IPHONE && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_WATCH

#define SD_MAC 1

else

#define SD_MAC 0

endif

該指令主要用于判斷當前平臺是不是MAC,單純使用TARGET_OS_MAC是不靠譜的。這樣判斷的缺點是,當Apple出現新的平臺時,判斷條件要修改。

TARGET_OS_IPHONE
TARGET_OS_IOS
TARGET_OS_TV
TARGET_OS_WATCH
SD_UIKIT
// iOS and tvOS are very similar, UIKit exists on both platforms
// Note: watchOS also has UIKit, but it's very limited

if TARGET_OS_IOS || TARGET_OS_TV

#define SD_UIKIT 1

else

#define SD_UIKIT 0

endif

iOS 和 tvOS 是非常相似的,UIKit在這兩個平臺中都存在,但是watchOS在使用UIKit時,是受限的。因此我們定義SD_UIKIT為真的條件是iOS 和 tvOS這兩個平臺。至于為什么要定義SD_UIKIT后邊會解釋的。

SD_IOS

if TARGET_OS_IOS

#define SD_IOS 1

else

#define SD_IOS 0

endif

SD_TV

if TARGET_OS_TV

#define SD_TV 1

else

#define SD_TV 0

endif

SD_WATCH

if TARGET_OS_WATCH

#define SD_WATCH 1

else

#define SD_WATCH 0

endif

平臺兼容適配

if SD_MAC

#import <AppKit/AppKit.h>
#ifndef UIImage
    #define UIImage NSImage
#endif
#ifndef UIImageView
    #define UIImageView NSImageView
#endif
#ifndef UIView
    #define UIView NSView
#endif

else

#if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
    #error SDWebImage doesn't support Deployment Target version < 5.0
#endif

#if SD_UIKIT
    #import <UIKit/UIKit.h>
#endif
#if SD_WATCH
    #import <WatchKit/WatchKit.h>
#endif

endif

觀察上邊的代碼,可以發現,在MAC平臺上進行了如下的轉換,這算是一個編程技巧:

UIImage -----> NSImage
UIImageView -----> NSImageView
UIView -----> NSView
SDWebImage不支持5.0以下的iOS版本。SD_UIKIT為真時,導入UIKit,SD_WATCH為真時,導入WatchKit。

基礎設置

ifndef NS_ENUM

define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type

endif

ifndef NS_OPTIONS

define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type

endif

if OS_OBJECT_USE_OBJC

#undef SDDispatchQueueRelease
#undef SDDispatchQueueSetterSementics
#define SDDispatchQueueRelease(q)
#define SDDispatchQueueSetterSementics strong

else

#undef SDDispatchQueueRelease
#undef SDDispatchQueueSetterSementics
#define SDDispatchQueueRelease(q) (dispatch_release(q))
#define SDDispatchQueueSetterSementics assign

endif

接口
extern UIImage *SDScaledImageForKey(NSString *key, UIImage *image);

typedef void(^SDWebImageNoParamsBlock)();

extern NSString *const SDWebImageErrorDomain;

static int64_t kAsyncTestTimeout = 5;
dispatch_main_async_safe
我們來看看這個宏,按理說我使用dispatch_main_async就可以了,為什么要加入safe呢?那么這個safe主要是解決那些不安全的問題呢?

ifndef dispatch_main_async_safe

define dispatch_main_async_safe(block)\

if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\
    block();\
} else {\
    dispatch_async(dispatch_get_main_queue(), block);\
}

endif

第一,我們可以像這樣在定義宏的時候使用換行,但需要添加 操作符
第二,如果當前線程已經是主線程了,那么在調用dispatch_async(dispatch_get_main_queue(), block)有可能會出現crash
第三,如果當前線程是主線程,直接調用,如果不是,調用dispatch_async(dispatch_get_main_queue(), block)
UIImage SDScaledImageForKey(NSString key, UIImage *image)
inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {
if (!image) {
return nil;
}

if SD_MAC

return image;

elif SD_UIKIT || SD_WATCH

if ((image.images).count > 0) {
    NSMutableArray<UIImage *> *scaledImages = [NSMutableArray array];

    for (UIImage *tempImage in image.images) {
        [scaledImages addObject:SDScaledImageForKey(key, tempImage)];
    }

    return [UIImage animatedImageWithImages:scaledImages duration:image.duration];
}
else {

if SD_WATCH

    if ([[WKInterfaceDevice currentDevice] respondsToSelector:@selector(screenScale)]) {

elif SD_UIKIT

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {

endif

        CGFloat scale = 1;
        if (key.length >= 8) {
            NSRange range = [key rangeOfString:@"@2x."];
            if (range.location != NSNotFound) {
                scale = 2.0;
            }
            
            range = [key rangeOfString:@"@3x."];
            if (range.location != NSNotFound) {
                scale = 3.0;
            }
        }

        UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
        image = scaledImage;
    }
    return image;
}

endif

}
這個方法是根據key來修改圖片的尺寸,需要注意的地方有:

inline 內聯函數
遞歸函數
總結
通過對該配置文件的理解,讓我對配置相關的信息更加了解了,我產生了收集這些預編譯的想法,生成一個內容比較豐富的文件,能夠很好地讓別人拿過去用。代碼應該寫的簡潔,穩定。

SDWebImage源碼解讀 之 NSData+ImageContentType 簡書 博客園
SDWebImage源碼解讀 之 UIImage+GIF 簡書 博客園

轉載:http://www.cnblogs.com/machao/p/6137517.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內容