前言
网上有很多SDWebImage的源码分析贴,现想自己开一篇写上自己学习的点点滴滴,希望激励自己的技术能更进一步.
开篇
做为第一篇当然是弄清楚这个工具要做的是什么,那对于我们程序员来说就是一种面对过程的理解方法,那么这个第一篇就用面对过程的方法写出自己的理解.
不多说了直接上图:
//1.内存中去寻找有没有这个图
//如果有就直接显示出来
//2.内存中没有这个图就到磁盘中去找
//磁盘中找到了就缓存到内存当中,并显示出来
//3.都没找到去网络上下载
//如果下载成功,保存到内存和磁盘当中
//显示图片
先准备一点东西,写一个继承自NSCache的自己的内存缓存单例类:
+(LYCache*)sharedCache{
static dispatch_once_t once;
static id instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
另一个是MD5加密的方法,这个方法可以直接SDWebImage拿过来(估计还可以拿很多的工具0.0),存储图片的名字都是通过MD5加密之后存起来的,可能是这样看上去会比较舒服一点:
- (NSString *)cachedFileNameForKey:(NSString *)key {
const char *str = [key UTF8String];
if (str == NULL) {
str = "";
}
unsigned char r[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), r);
NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],
r[11], r[12], r[13], r[14], r[15], [[key pathExtension] isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", [key pathExtension]]];
return filename;
}
下面就可以去填满上面的空缺了:
self.imageUrl = @"http://img12.360buyimg.com/n0/jfs/t289/30/1219748821/432500/b67cb240/543394bcN0cd63cef.jpg";
NSString *key = [self cachedFileNameForKey:self.imageUrl];
//1.内存中去寻找有没有这个图,这个查询应该是异步的,后面封装的时候再处理
LYCache *cache = [LYCache sharedCache];
UIImage *image = [cache objectForKey:key];
if (image) {
self.imageView.image = image;
}else{
//2.内存中没有这个图就到磁盘中去找
//磁盘中找到了缓存到内存当中
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray*path =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
NSString*documentPath = [path lastObject];
NSString *cachePath = [NSString stringWithFormat:@"%@/myCache",documentPath];
cachePath = [cachePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",key]];
BOOL isOne = [fileManager fileExistsAtPath:cachePath];
if (isOne) {
//保存到内存当中
LYCache *cache = [LYCache sharedCache];
[cache setObject:image forKey:key];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfFile:cachePath]];
self.imageView.image = image;
}else{
//3.都没找到去网络上下载
//开启下载
NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session =[NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
NSURLSessionDownloadTask *getImageTask = [session downloadTaskWithURL:[NSURL URLWithString:self.imageUrl]];
[getImageTask resume];
}
}
下载的代理方法:
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSData *imageData = [NSData dataWithContentsOfURL:location];
if (imageData) {
UIImage *downloadImage = [UIImage imageWithData:imageData];
//保存到内存当中
LYCache *cache = [LYCache sharedCache];
NSString *key = [self cachedFileNameForKey:self.imageUrl];
[cache setObject:downloadImage forKey:key];
//保存到磁盘当中
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray*path =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
NSString*documentPath = [path lastObject];
NSString *cachePath = [NSString stringWithFormat:@"%@/myCache",documentPath];
//如果没有这文件夹就创建文件夹
if (![fileManager fileExistsAtPath:cachePath]) {
[fileManager createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:nil];
}
cachePath = [cachePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",key]];
BOOL isSuccess = [fileManager createFileAtPath:cachePath contents:imageData attributes:nil];
if (isSuccess) {
NSLog(@"存储成功");
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = downloadImage;
});
}else{
NSLog(@"存储失败");
}
}
}
总结:
自己一写才知道要很完美估计是不能的,但是一边看SDWebImage的源码才看出自己的很多的不足,后面的章节要开始封装了,还是对照的SDWebImage来一点点写下去,希望能从中学到更多的东西(面对对象的思想,架构的思想,一些奇特的用法等等),也希望大家多给意见.