读 SDWebImage 六 (编码器三:SDWebImageCodersManager)
声明属性和方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| /** 单例初始化 */ + (nonnull instancetype)sharedInstance;
/** 所有的编解码器都在这个编解码器管理中(编码器数组)这个编解码器数组是一个优先级对列, 这意味着最后添加的编解码器拥有最高的优先级 */ @property (nonatomic, copy, readwrite, nullable) NSArray<id<SDWebImageCoder>> *coders;
/** 在编解码器数组的末尾添加一个新的编解码器。 新添加的编解码器优先级最高。
@param coder 需添加的coder */ - (void)addCoder:(nonnull id<SDWebImageCoder>)coder;
/** 在编解码器数组中移除编码器
@param coder 需移除的coder */ - (void)removeCoder:(nonnull id<SDWebImageCoder>)coder;
|
初始化方法实现
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| //单例 + (nonnull instancetype)sharedInstance { static dispatch_once_t once; static id instance; dispatch_once(&once, ^{ instance = [self new]; }); return instance; }
- (instancetype)init { if (self = [super init]) { // 初始化默认的编解码器,默认编码器只有SDWebImageImageIOCoder类型的 NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder]] mutableCopy]; #ifdef SD_WEBP //如果是WEBP,就添加SDWebImageWebPCoder单例 [mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]]; #endif _coders = [mutableCoders copy]; _codersLock = dispatch_semaphore_create(1); } return self; }
|
编码器IO操作
添加编码器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| - (void)addCoder:(nonnull id<SDWebImageCoder>)coder { //判断要添加的编解码器是否遵守SDWebImageCoder协议,以提供最基本的编解码功能 //如果不遵守SDWebImageCoder协议,返回 if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) { return; } LOCK(self.codersLock); //临时变量,编解码器数组,如果不存在,重新初始化一个 NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [self.coders mutableCopy]; if (!mutableCoders) { mutableCoders = [NSMutableArray array]; } //添加新的coder [mutableCoders addObject:coder]; //重新赋值给self.coders self.coders = [mutableCoders copy]; UNLOCK(self.codersLock); }
|
移除编码器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| - (void)removeCoder:(nonnull id<SDWebImageCoder>)coder { //判断要添加的编解码器是否遵守SDWebImageCoder协议,以提供最基本的编解码功能 //如果不遵守SDWebImageCoder协议,返回 if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) { return; } LOCK(self.codersLock); //临时变量,编解码器数组,使其等于self.coders(深拷贝) NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [self.coders mutableCopy]; //移除编解码器coder [mutableCoders removeObject:coder]; //重新赋值给self.coders self.coders = [mutableCoders copy]; UNLOCK(self.codersLock); }
|
SDWebImageCoder协议方法实现
解码协议实现
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 71
| /** 如果此编解码器可以解码某些data,返回YES,否则,它应该传递给另一个编码器 @param data 需要解码的图片数据 @return 如果此编解码器可以解码图片数据,返回YES,否则返回NO */ - (BOOL)canDecodeFromData:(NSData *)data { LOCK(self.codersLock); //临时变量,编解码器数组,赋值等于 self.coders NSArray<id<SDWebImageCoder>> *coders = self.coders; UNLOCK(self.codersLock); //倒序遍历编解码器数组(倒序的原因是:编解码器数组中最新添加的具有最高优先级) for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) { //判断,如果其中有编解码器能够解码,就返回YES,否则返回NO if ([coder canDecodeFromData:data]) { return YES; } } return NO; }
/** 将图片数据解码为图片。 @param data 需要解码的图片数据 @return 解码后得到的图片 */ - (UIImage *)decodedImageWithData:(NSData *)data { LOCK(self.codersLock); NSArray<id<SDWebImageCoder>> *coders = self.coders; UNLOCK(self.codersLock); //倒序遍历编解码器列表 for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) { //判断,如果其中有编解码器能够解码,就执行解码操作,否则返回Image为nil if ([coder canDecodeFromData:data]) { return [coder decodedImageWithData:data]; } } return nil; }
/** 使用原始图片和图片数据解压缩图片。
@param image 需要压缩的原图片 @param data 指向原始图像数据的指针。 指针本身是非空的,但图像数据可以为空。 如果需要,此数据将设置为缓存。 如果您不需要同时修改数据,请忽略此参数。 @param optionsDict 一个包含任何解压缩选项的字典。 通过{SDWebImageCoderScaleDownLargeImagesKey:@(YES)}缩小大图像 @return 解压缩后的图片 */ - (UIImage *)decompressedImageWithImage:(UIImage *)image data:(NSData *__autoreleasing _Nullable *)data options:(nullable NSDictionary<NSString*, NSObject*>*)optionsDict { //如果image不存在,返回nil if (!image) { return nil; } LOCK(self.codersLock); NSArray<id<SDWebImageCoder>> *coders = self.coders; UNLOCK(self.codersLock); //倒序遍历编解码器列表 for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) { //如果其中有编解码器可以解码,执行解压缩图片操作,并返回解压缩后的图片 if ([coder canDecodeFromData:*data]) { //解压缩图片操作 UIImage *decompressedImage = [coder decompressedImageWithImage:image data:data options:optionsDict]; decompressedImage.sd_imageFormat = image.sd_imageFormat; return decompressedImage; } } return nil; }
|
编码协议实现
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
| /** 如果此编码器可以编码某些图片格式,返回YES,否则,它应该传递给另一个编码器 @param format 图片格式 @return 如果此编码器可以编码图片格式,返回YES,否则返回NO */ - (BOOL)canEncodeToFormat:(SDImageFormat)format { LOCK(self.codersLock); NSArray<id<SDWebImageCoder>> *coders = self.coders; UNLOCK(self.codersLock); //倒序遍历编解码器列表 for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) { //判断,如果其中有编解码器能够编码图片格式,就返回YES,否则返回NO if ([coder canEncodeToFormat:format]) { return YES; } } return NO; }
/** 将图片编码为图片数据(imagedata)
@param image 需要编码的图片 @param format 要编码的图片格式, 也有可能是 `SDImageFormatUndefined` 格式(未识别格式) @return The encoded image data */ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format { //如果image不存在,返回nil if (!image) { return nil; } LOCK(self.codersLock); NSArray<id<SDWebImageCoder>> *coders = self.coders; UNLOCK(self.codersLock); //倒序遍历编解码器列表 for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) { //判断,如果其中有编解码器能够编码图片格式,就执行将图片以format格式编码为data操作,并返回imagedata if ([coder canEncodeToFormat:format]) { // 将图片编码为图片数据(imagedata) return [coder encodedDataWithImage:image format:format]; } } return nil; }
|