写在前面的话
阅读第三方类是提高技术水平的一个很好的方式,通过看优秀的第三方类,来明白优秀的框架是如何实现功能的,需要从中明白实现原理,设计方式,编程习惯和方式,搞清楚其中的每一个知识点,然后进行提炼,变成自己的东西。
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
}
需要注意的只是点是:
网友评论