進擊的SDWebImage(一)

前言

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容