SDWebImage其他一些相关类源码阅读记录

目录

  1. UIView+WebCacheOperation
  2. SDWebImagePrefetcher

UIView+WebCacheOperation

下面我们先来看看UIView+WebCacheOperation里面都写了些什么:
UIView+WebCacheOperation这个分类提供了三个方法,用于操作绑定关系

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
#import <UIKit/UIKit.h>
#import "SDWebImageManager.h"
@interface UIView (WebCacheOperation)
/**
* Set the image load operation (storage in a UIView based dictionary)
设置图像加载操作(存储在和UIView做绑定的字典里面)
*
* @param operation the operation
* @param key key for storing the operation
*/
- (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key;
/**
* Cancel all operations for the current UIView and key
用这个key找到当前UIView上面的所有操作并取消
*
* @param key key for identifying the operations
*/
- (void)sd_cancelImageLoadOperationWithKey:(NSString *)key;
/**
* Just remove the operations corresponding to the current UIView and key without cancelling them
*
* @param key key for identifying the operations
*/
- (void)sd_removeImageLoadOperationWithKey:(NSString *)key;

为了方便管理和找到视图正在进行的一些操作,WebCacheOperation将每一个视图的实例和它正在进行的操作(下载和缓存的组合操作)绑定起来,实现操作和视图一一对应关系,以便可以随时拿到视图正在进行的操作,控制其取消等,如何进行绑定我们在下面分析:
UIView+WebCacheOperation.m文件内
- (NSMutableDictionary *)operationDictionary用到了<objc/runtime.h>中定义的两个函数:

• objc_setAssociatedObject
• objc_getAssociatedObject

objc_setAssociatedObject作用是对已存在的类在扩展中添加自定义的属性 ,通常推荐的做法是添加属性的key最好是static char类型的,通常来说该属性的key应该是常量唯一的.
objc_getAssociatedObject根据key获得与对象绑定的属性.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (NSMutableDictionary *)operationDictionary {
/*
这个loadOperationKey 的定义是:static char loadOperationKey;
它对应的绑定在UIView的属性是operationDictionary(NSMutableDictionary类型)
operationDictionary的value是操作,key是针对不同类型视图和不同类型的操作设定的字符串
注意:&是一元运算符结果是右操作对象的地址(&loadOperationKey返回static char loadOperationKey的地址)
*/
NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey);
//如果可以查到operations,就rerun,反正给视图绑定一个新的,空的operations字典
if (operations) {
return operations;
}
operations = [NSMutableDictionary dictionary];
objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return operations;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)sd_cancelImageLoadOperationWithKey:(NSString *)key {
// 取消正在下载的队列
NSMutableDictionary *operationDictionary = [self operationDictionary];
//如果 operationDictionary可以取到,根据key可以得到与视图相关的操作,取消他们,并根据key值,从operationDictionary里面删除这些操作
id operations = [operationDictionary objectForKey:key];
if (operations) {
if ([operations isKindOfClass:[NSArray class]]) {
for (id <SDWebImageOperation> operation in operations) {
if (operation) {
[operation cancel];
}
}
} else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){
[(id<SDWebImageOperation>) operations cancel];
}
[operationDictionary removeObjectForKey:key];
}
}

SDWebImagePrefetcher

Prefetch some URLs in the cache for future use. Images are downloaded in low priority.
预取缓存中的一些URL以供将来使用。 图像以低优先级下载。

两个代理方法

1
2
3
4
//当图像被预取完时调用
- (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount;
//当全部图像被预取完时调用
- (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount;

核心方法循环遍历- (void)startPrefetchingAtIndex:(NSUInteger)index {}调用SDWebImageManager的实例方法- (id <SDWebImageOperation>)downloadImageWithURL: options: progress: completed:
获取图片

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
- (void)startPrefetchingAtIndex:(NSUInteger)index {
if (index >= self.prefetchURLs.count) return;
self.requestedCount++;
[self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!finished) return;
self.finishedCount++;
if (image) {
if (self.progressBlock) {
self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
}
}
else {
if (self.progressBlock) {
self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
}
// Add last failed
self.skippedCount++;
}
if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) {
[self.delegate imagePrefetcher:self
didPrefetchURL:self.prefetchURLs[index]
finishedCount:self.finishedCount
totalCount:self.prefetchURLs.count
];
}
if (self.prefetchURLs.count > self.requestedCount) {
dispatch_async(self.prefetcherQueue, ^{
[self startPrefetchingAtIndex:self.requestedCount];
});
} else if (self.finishedCount == self.requestedCount) {
[self reportStatus];
if (self.completionBlock) {
self.completionBlock(self.finishedCount, self.skippedCount);
self.completionBlock = nil;
}
self.progressBlock = nil;
}
}];
}

相关阅读:
SDWebImage 源码阅读记录(一)
SDWebImageManager 源码阅读记录(二)
SDWebImageDownloader 源码阅读记录(三)
SDWebImageDownloaderOperation 源码阅读记录(四)
SDWebImageCache 源码阅读记录(五)
SDWebImage相关类 源码阅读记录(六)