一、SDWebImage源码解读SDWebImageCompat

写在前面的话

阅读第三方类是提高技术水平的一个很好的方式,通过看优秀的第三方类,来明白优秀的框架是如何实现功能的,需要从中明白实现原理,设计方式,编程习惯和方式,搞清楚其中的每一个知识点,然后进行提炼,变成自己的东西。

SDWebImageCompat是SDWebImage的配置文件

 1. #import导入这个头文件,能访问系统提供的配置选项。这个文件里面全部都是宏定义,主要定义了Apple 各系统平台和各CPU类型相关的宏。主要用于开发的时候针对不同的开发环境做配置使用。

2. __OBJC_GC__ 条件编译

#ifdef __OBJC_GC__

    #error SDWebImage does not support Objective-C Garbage Collection

#endif

SDWebImage 不支持GC,如果宏定义过 __OBJC_GC__,则表示是在支持GC 的开发环境,直接报错(#error)。

3. 平台判断  :我们只需要知道 SD_UIKIT代表 tvOS和iOS平台 ,SD_WATCH代表 watchOS平台

4.dispatch_main_async_safe

#ifndef dispatch_queue_async_safe

#define dispatch_queue_async_safe(queue, block)\

    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) {\

        block();\

    } else {\

        dispatch_async(queue, block);\

    }

#endif

这样做的好处是:

第一,我们可以像这样在定义宏的时候使用换行,但需要添加 \ 操作符

第二,如果当前线程已经是主线程了,那么在调用dispatch_async(dispatch_get_main_queue(), block)有可能会出现crash

第三,如果当前线程是主线程,直接调用,如果不是,调用dispatch_async(dispatch_get_main_queue(), block)

5.UIImage *SDScaledImageForKey(NSString *key, UIImage *image); 给定一张图片,通过参数key调整scale属性,返回对应分辨率下面的图片

6.定义枚举

#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

7. SDWebImageCompat.m 的实现

/* 给定一张图片,通过参数key调整scale属性,返回对应分辨率下面的图片

@param key 图片名称

@param image 资源图片

@return 处理以后的图片

*/

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) { //如果是动态图片,比如GIF图片,则递归处理 NSMutableArray *scaledImages = [NSMutableArray array];

        for (UIImage *tempImage in image.images) {

            [scaledImages addObject:SDScaledImageForKey(key, tempImage)];

        }

        //把处理结束的图片再合成一张动态图片

        UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];

        if (animatedImage) {

            animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;

        }

        return animatedImage;

    } else {

#if SD_WATCH

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

#elif SD_UIKIT

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

#endif

            //指定图片大小 2x 3x

            CGFloat scale = 1;

            if (key.length >= 8) {// “@2x.png”的长度为7,所以此处添加了这个判断

                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

}

需要注意的只是点是:

 内联函数

你可能感兴趣的:(一、SDWebImage源码解读SDWebImageCompat)