前言
網上有很多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來一點點寫下去,希望能從中學到更多的東西(面對對象的思想,架構的思想,一些奇特的用法等等),也希望大家多給意見.