自定义图片下载

学习完SDWebImage第三方框架之后,根据它的流程,试着简写自定义下载图片的方法。

创建单例

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
#pragma mark - 单例
static CHImageManager *_sharedInstance;
+ (CHImageManager *)sharedManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!_sharedInstance) {
_sharedInstance = [[CHImageManager alloc] init];
}
});
return _sharedInstance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [super allocWithZone:zone];
});
return _sharedInstance;
}

- (instancetype)init
{
self = [super init];
if (self) {

}
return self;
}

设置URL缓存过滤器并给出方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//定义缓存过滤器的block块
typedef NSString *(^CHImageCacheKeyFilterBlock)(NSURL *url);

@property (nonatomic, copy) CHImageCacheKeyFilterBlock cacheKeyFilter; //缓存过滤器


#pragma mark - URL过滤器
//返回指定URL的缓存键值,就是URL字符串
- (NSString *)cacheKeyForURL:(NSURL *)url {
//如果URL不存在,那么就返回空
if (!url) {
return @"";
}

//先判断是否设置了缓存过滤器,如果设置了则走cacheKeyFilterBlock,否则直接把URL转换为字符串之后返回
if (self.cacheKeyFilter) {
return self.cacheKeyFilter(url);
} else {
return [url absoluteString];
}
}

需要外部自己设置过滤规则 实现cacheKeyFilter相关

自定义下载方法

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
- (void)customImageView:(UIImageView *)imageView UrlStr:(NSURL *)urlStr{

//容错处理
if ([urlStr isKindOfClass:NSString.class]) {
urlStr = [NSURL URLWithString:(NSString *)urlStr];
}

if (![urlStr isKindOfClass:NSURL.class]) {
urlStr = nil;
}

if (!urlStr) {
return;
}

// 缓存key
NSString *cacheKey = [self cacheKeyForURL:urlStr];

/* 从内存缓存中取 */
UIImage *image = [self.imagesCache objectForKey:cacheKey];
if (image) {
// 直接设置
imageView.image = image;
}else{
/* 检查磁盘缓存 */
// 获取文件路径
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 获取图片名称 获取节点
NSString *fileName = [cacheKey lastPathComponent];
// 拼接文件全路径
NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName];
// 从磁盘缓存中取
NSData *data = [NSData dataWithContentsOfFile:fullPath];

if (data) {
// 将二进制数据转成图片
UIImage *image = [UIImage imageWithData:data];
// 设置图片
imageView.image = image;
// 把图片存到内存缓存中
[self.imagesCache setObject:image forKey:cacheKey];
}else{
/* 检查操作缓存 */
// 清空图片或者占位图片
imageView.image = nil;
// 检查操作缓存
NSBlockOperation *downloadOperation = [self.operationsCache objectForKey:cacheKey];
if (downloadOperation) {
// 不处理

}else{
downloadOperation = [NSBlockOperation blockOperationWithBlock:^{
// 下载图片三部曲
NSData *tempData = [NSData dataWithContentsOfURL:urlStr];
UIImage *tempImage = [UIImage imageWithData:tempData];
if (tempImage == nil) {
// 移除操作缓存中的操作
[self.operationsCache removeObjectForKey:cacheKey];
return ;
}
// 把图片存到内存缓存
[self.imagesCache setObject:tempImage forKey:cacheKey];

// 把图片保存到磁盘缓存
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[data writeToFile:fullPath atomically:YES];
});

// 回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 设置图片
//imageView.image = tempImage;
// 刷新一行(会重新调用cellForRow方法)
                      //[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];

}];
}];
// 添加操作缓存
[self.operationsCache setObject:downloadOperation forKey:cacheKey];
// 将操作加入队列
[self.queue addOperation:downloadOperation];
}
}
}
}

移除缓存策略

1
2
3
4
5
6
7
8
9
#pragma mark - 清除缓存
- (void)cleanCache{
// 内存缓存
[self.imagesCache removeAllObjects];
// 操作缓存
[self.operationsCache removeAllObjects];
// 取消队列中的操作
[self.queue cancelAllOperations];
}

这里是具体实现方法 点击查看