該文章閱讀的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