SDWebImage之SDWebImageCompat

SDWebImageCompat 是SDWebImage 的配置文件,里面利用条件编译对Apple 的各个平台进行了兼容。从源码中可以看到SDWebImage 支持当前的MAC/iOS/TV/WATCH 平台,这种适配各个平台的兼容,对框架开发意义重大。

1.#import <TargetConditionals.h>

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1e9421 }
span.s1 { }
span.s2 { font: 18.0px Menlo }

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

2.条件编译__OBJC_GC__

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1e9421 }
span.s1 { font: 18.0px Menlo }
span.s2 { }

#ifdef __OBJC_GC__
    #error SDWebImage does not support Objective-C Garbage Collection
#endif

Objective-C 支持内存的垃圾回收机制(Garbage collection 简称:GC)。在Mac开发是支持的,但是在iOS 开发中使用MRC/ARC,是不支持GC 的。iOS 5 之后开始支持ARC ,帮助开发者更好的管理内存,简化内存管理的难度并提高开发效率。SDWebImage 不支持GC,如果宏定义过 __OBJC_GC__,则表示是在支持GC 的开发环境,直接报错(#error)。当启动GC时,所有的retain、autorelease、release 和dealloc 方法都将被系统忽略。

3.SD_MAC

#if !TARGET_OS_IPHONE && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_WATCH
    #define SD_MAC 1
#else
    #define SD_MAC 0
#endif

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1e9421 }
span.s1 { }
span.s2 { font: 18.0px Menlo }

判断当前平台是不是MAC。TARGET_OS_MAC 定义在所有的平台中,比如MAC、iPhone、Watch、TV等,因此单纯的使用TARGET_OS_MAC 判断当前是不是MAC 平台是不可行的。但按照上面的判断方式,也存在一个缺点:当Apple出现新的平台时,判断条件要修改

4.SD_UIKIT

#if TARGET_OS_IOS || TARGET_OS_TV
    #define SD_UIKIT 1
#else
    #define SD_UIKIT 0
#endif

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1e9421 }
span.s1 { font: 18.0px Menlo }
span.s2 { }

iOS 和 tvOS 是非常相似的,UIKit在这两个平台中都存在,但是watchOS在使用UIKit时,是受限的。因此定义SD_UIKIT为真的条件是iOS 和 tvOS这两个平台。

5.SD_IOS&&SD_TV&&SD_WATCH

#if TARGET_OS_IOS
    #define SD_IOS 1
#else
    #define SD_IOS 0
#endif

#if TARGET_OS_TV
    #define SD_TV 1
#else
    #define SD_TV 0
#endif

#if TARGET_OS_WATCH
    #define SD_WATCH 1
#else
    #define SD_WATCH 0
#endif

这三个宏定义用于区分iOS、TV、WATCH三个平台。

6.平台兼容适配

#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
    //SDWebImage不支持5.0以下的iOS版本
    #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
  • 如果SD_MAC 为真,表示在macOS 平台上开发,引入 并定义了三个宏 UIImage/UIImageView/UIView;
  • SDWebImage 不支持iOS 5.0 以下的版本;
  • SD_UIKIT 为真时引入 <UIKit/UIKit.h>;
  • SD_WATCH 为真时引入 <WatchKit/WatchKit.h>。

7. NS_ENUM/NS_OPTIONS

#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

用于枚举类型。

8.OS_OBJECT_USE_OBJC

#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

OS_OBJECT_USE_OBJC宏定义是在6.0版本之后才出现的。该宏定义主要是针对GCD 的,GCD 中的对象在6.0之前是不参与ARC的,而6.0之后 在ARC下使用GCD不用关心释放问题。  对于最低sdk 版本 >= iOS 6.0来说,GCD 对象已经纳入了ARC 的管理范围,我们就不需要再手工调用 dispatch_release 了;否则的话,在sdk < 6.0的时候;即使开启了ARC ,这个宏OS_OBJECT_USE_OBJC 也是没有的,也就是说这个时候,GCD对象还必须得自己管理。

如果开发的项目最低目标低于 iOS 6.0 or Mac OS X 10.8,应该自己管理GCD对象;使用(dispatch_retain ,dispatch_release),ARC 并不会去管理它们。

如果开发的项目最低目标是 iOS 6.0 or Mac OS X 10.8 或者更高的,ARC 已经能够管理GCD 对象了,这时候GCD 对象就如同普通的OC 对象一样,不应该使用dispatch_retain , ordispatch_release 。

9.API

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

typedef void(^SDWebImageNoParamsBlock)();

extern NSString *const SDWebImageErrorDomain;

static int64_t kAsyncTestTimeout = 5;

10.dispatch_main_async_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

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1e9421 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #1e9421 }
span.s1 { }
span.s2 { font: 18.0px Menlo }
span.s3 { font: 18.0px "PingFang SC" }

在主线程中安全的执行任务Block。

在项目中,如果当前线程已经是主线程,那么在调用dispatch_async(dispatch_get_main_queue(), block)有可能会出现crash。因此做了一个判断:当前线程是主线程,直接调用Block;如果不是,那么调用dispatch_async(dispatch_get_main_queue(), block)。

11.全局方法SDScaledImageForKey

/**
 给定一张图片,通过参数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
    //如果是动态图片,比如GIF图片,则迭代处理
    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;
            // “@2x.png”的长度为7,所以此处添加了这个判断,很巧妙
            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
}

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c81b13 }
span.s1 { color: #822d0f }
span.s2 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822d0f }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822d0f }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822d0f }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822d0f }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822d0f }
span.s1 { }

时间: 2024-10-11 04:47:11

SDWebImage之SDWebImageCompat的相关文章

李洪强详细介绍SDWebImage

SDWebImage是一个开源的第三方库,它提供了UIImageView的一个分类,以支持从远程服务器下载并缓存图片的功能.它具有以下功能: 提供UIImageView的一个分类,以支持网络图片的加载与缓存管理 一个异步的图片加载器 一个异步的内存+磁盘图片缓存 支持GIF图片 支持WebP图片 后台图片解压缩处理 确保同一个URL的图片不被下载多次 确保虚假的URL不会被反复加载 确保下载及缓存时,主线程不被阻塞 从github上对SDWebImage使用情况就可以看出,SDWebImage在

SDWebImage源码学习笔记

//  这是我第二次学习sdwebimage源码,第一次学习吸收的很少,看不懂啊.第二次看个50%,在此记录一点笔记. 首先是目录: 1.SDWebImage目录 里面有两个类,SDWebImageCompat.h 里面有个根据屏幕设置图片scale的方法 SDWebImageOperation.h 声明了一个协议,取消操作 (可以理解这一个放的公共方法目录) 2.Downloader 目录(顾名思义,下载操作相关的目录)里面有两个关键的类 SDWebImageDownloaderOperati

通读SDWebImage源码

SDWebImage是iOS开发者经常使用的一个开源框架,这个框架的主要作用是:一个异步下载图片并且支持缓存的UIImageView分类. #import <Foundation/Foundation.h> #import "SDWebImageCompat.h" typedef NS_ENUM(NSInteger, SDImageCacheType) { /** * The image wasn't available the SDWebImage caches, but

你真的懂SDWebImage?

源码来源:  https://github.com/rs/SDWebImage 版本: 3.7 SDWebImage是一个开源的第三方库,它提供了UIImageView的一个分类,以支持从远程服务器下载并缓存图片的功能.它具有以下功能: 提供UIImageView的一个分类,以支持网络图片的加载与缓存管理 一个异步的图片加载器 一个异步的内存+磁盘图片缓存 支持GIF图片 支持WebP图片 后台图片解压缩处理 确保同一个URL的图片不被下载多次 确保虚假的URL不会被反复加载 确保下载及缓存时,

源码篇:SDWebImage

攀登,一步一个脚印,方能知其乐 源码篇:SDWebImage 源码来源:https://github.com/rs/SDWebImage 版本: 3.7 SDWebImage是一个开源的第三方库,它提供了UIImageView的一个分类,以支持从远程服务器下载并缓存图片的功能.它具有以下功能: 提供UIImageView的一个分类,以支持网络图片的加载与缓存管理 一个异步的图片加载器 一个异步的内存+磁盘图片缓存 支持GIF图片 支持WebP图片 后台图片解压缩处理 确保同一个URL的图片不被下

SDWebImage源码阅读前的准备(一)预处理条件编译

阅读前的扩展: 条件编译:#ifdef #elif #ifndef #if #else #endif 的用法,及 #define #undef 的用法. #ifdef/#elif/#ifndef/#if/#else/#endif 这几个条件编译指令是在进行条件编译的时候使用的. 学习条件编译首先对C语言的预处理进行学习,C语言由源代码生成的各阶段如下: C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件 其中 编译预处理阶段,读取c源程序,

SDWebImage源码解析之SDWebImageManager的注解

http://www.cocoachina.com/ios/20150612/12118.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

IOS 使用SDWebImage实现仿新浪微博照片浏览器

使用第三方库SDWebImage实现仿新浪微博照片浏览器,可以下载图片缓存,点击之后滚动查看相片,具体效果如下: 代码如下: WeiboImageView.h: #import <UIKit/UIKit.h> @interface WeiboImageView : UIImageView @property (nonatomic, assign) CGRect originRect; - (instancetype)initWithFrame:(CGRect)frame; @end Weibo

SDWebImage 使用

原文地址:http://www.cnblogs.com/YouXianMing/p/3604851.html UIImageView的类目,支持异步图片下载,支持缓存机制 SDWebImage库给UIImageView提供类目,支持远程下载图片(从网络上),功能如下: 一个UIImageView的类目,给 Cocoa Touch 框架添加了异步下载远程图片以及管理图片缓存的功能 一个图片的异步下载器 一个内存 + 磁盘的缓存机制,并自动管理 gif动画支持 WebP格式支持 后台解压图片 确保同