该文章阅读的SDWebImage的版本为4.3.3。
这个类遵守了SDWebImageCoder
协议,意味着这个类可以提供基本的编解码功能。
1.公共属性
/**
这个属性中保存着各种类型的编解码器
*/
@property (nonatomic, strong, readwrite, nullable) NSArray<SDWebImageCoder>* coders;
2.公共方法
/**
添加编解码器
*/
- (void)addCoder:(nonnull id<SDWebImageCoder>)coder;
/**
移除编辑吗器
*/
- (void)removeCoder:(nonnull id<SDWebImageCoder>)coder;
3.私有属性
/**
保存该类管理的所有编解码器
*/
@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCoder>* mutableCoders;
/**
操作编解码器数组的队列
*/
@property (strong, nonatomic, nullable) dispatch_queue_t mutableCodersAccessQueue;
4.公共方法的实现
+ (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类型的
_mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder]] mutableCopy];
#ifdef SD_WEBP
[_mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]];
#endif
// 创建一个并发队列用于管理编解码器数组
_mutableCodersAccessQueue = dispatch_queue_create("com.hackemist.SDWebImageCodersManager", DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
- (void)addCoder:(nonnull id<SDWebImageCoder>)coder {
// 判断要添加的编解码器是否遵守了SDWebImageCoder协议,以提供最基本的编解码功能
if ([coder conformsToProtocol:@protocol(SDWebImageCoder)]) {
// 利用GCD的栅栏功能保证数组在“写”的时候线程的安全
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
// 保存编解码器
[self.mutableCoders addObject:coder];
});
}
}
- (void)removeCoder:(nonnull id<SDWebImageCoder>)coder {
// 利用GCD的栅栏功能保证数组在“写”的时候线程的安全
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
// 移除编解码器
[self.mutableCoders removeObject:coder];
});
}
5. 公共属性的读写方法
- (NSArray<SDWebImageCoder> *)coders {
// 创建变量保存编解码器数组
__block NSArray<SDWebImageCoder> *sortedCoders = nil;
// 自定义并发队列同步执行
dispatch_sync(self.mutableCodersAccessQueue, ^{
// 获取保存编解码器数组数组的倒序数组
sortedCoders = (NSArray<SDWebImageCoder> *)[[[self.mutableCoders copy] reverseObjectEnumerator] allObjects];
});
// 返回编解码器数组
return sortedCoders;
}
- (void)setCoders:(NSArray<SDWebImageCoder> *)coders {
// 利用GCD的栅栏功能保证数组在“写”的时候线程的安全
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
// 直接保存
self.mutableCoders = [coders mutableCopy];
});
}
6.SDWebImageCoder协议方法的实现
- 解码
- (BOOL)canDecodeFromData:(NSData *)data {
// 遍历编解码器数组
for (id<SDWebImageCoder> coder in self.coders) {
// 如果其中有解码器能解码
if ([coder canDecodeFromData:data]) {
// 就返回YES
return YES;
}
}
return NO;
}
- (UIImage *)decodedImageWithData:(NSData *)data {
// 如果没有数据就返回空
if (!data) {
return nil;
}
// 遍历编解码器数组
for (id<SDWebImageCoder> coder in self.coders) {
// 如果其中有解码器能解码
if ([coder canDecodeFromData:data]) {
// 调用解码器解码并返回
return [coder decodedImageWithData:data];
}
}
return nil;
}
- (UIImage *)decompressedImageWithImage:(UIImage *)image
data:(NSData *__autoreleasing _Nullable *)data
options:(nullable NSDictionary<NSString*, NSObject*>*)optionsDict {
// 如果没有图片对象就不压缩了返回空
if (!image) {
return nil;
}
// 遍历编解码器数组
for (id<SDWebImageCoder> coder in self.coders) {
// 如果其中有解码器能解码
if ([coder canDecodeFromData:*data]) {
// 调用解码器压缩并返回
return [coder decompressedImageWithImage:image data:data options:optionsDict];
}
}
return nil;
}
- 编码
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
// 遍历编解码器数组
for (id<SDWebImageCoder> coder in self.coders) {
// 如果其中有编解码器能编码
if ([coder canEncodeToFormat:format]) {
// 就返回YES
return YES;
}
}
return NO;
}
- (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format {
// 如果没有图片对象就返回空
if (!image) {
return nil;
}
// 遍历编解码器数组
for (id<SDWebImageCoder> coder in self.coders) {
// 如果其中有解码器能编码
if ([coder canEncodeToFormat:format]) {
// 调用编解码器编码并返回
return [coder encodedDataWithImage:image format:format];
}
}
return nil;
}
7.总结
这个是是编解码器的管理类,管理着用于图像编解码的类,默认只有SDWebImageImageIOCoder
这个类,如果导入了WebP
,默认就会还有SDWebImageWebPCoder
类。
调用编解码器的顺序是后添加到数组的先调用,保证了用户如果自定义了编解码器,添加到该类后会被先调用。
源码阅读系列:SDWebImage
源码阅读:SDWebImage(二)——SDWebImageCompat
源码阅读:SDWebImage(三)——NSData+ImageContentType
源码阅读:SDWebImage(四)——SDWebImageCoder
源码阅读:SDWebImage(五)——SDWebImageFrame
源码阅读:SDWebImage(六)——SDWebImageCoderHelper
源码阅读:SDWebImage(七)——SDWebImageImageIOCoder
源码阅读:SDWebImage(八)——SDWebImageGIFCoder
源码阅读:SDWebImage(九)——SDWebImageCodersManager
源码阅读:SDWebImage(十)——SDImageCacheConfig
源码阅读:SDWebImage(十一)——SDImageCache
源码阅读:SDWebImage(十二)——SDWebImageDownloaderOperation
源码阅读:SDWebImage(十三)——SDWebImageDownloader
源码阅读:SDWebImage(十四)——SDWebImageManager
源码阅读:SDWebImage(十五)——SDWebImagePrefetcher
源码阅读:SDWebImage(十六)——SDWebImageTransition
源码阅读:SDWebImage(十七)——UIView+WebCacheOperation
源码阅读:SDWebImage(十八)——UIView+WebCache
源码阅读:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat
源码阅读:SDWebImage(二十)——UIButton+WebCache
源码阅读:SDWebImage(二十一)——UIImageView+WebCache/UIImageView+HighlightedWebCache