第三次讀Kingfisher網絡圖片緩存庫的思考與感覺

接下來咱們來作硬盤緩存,多張圖片加載,多張圖片緩存的多線程處理。這一節把這些都儘可能處理完,由於這個思路是sdwebimage的思路,確切的說跟名字的 Kingfisher庫,牽扯不是很大。因此儘早把本身的思路所有寫完,好再熟悉的基礎上去讀Kingfisherweb

需求開始:算法

如今我想給硬盤裏存,若是是第一次存儲那麼默認往硬盤裏存,別的狀況就能夠設置一個傳入的參數來告訴到底要不要往硬盤裏存,若是是Objective-c語言的話,咱們要寫兩個方法swift

一個:- (void)storeImage:(UIImage *)image forKey:(NSString *)key 。緩存

一個:- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk。 第一個方法裏,默認會調用第二個方法 而且傳 YES。:    [self storeImage:image forKey:key toDisk:YES];網絡

Swift就不用這麼麻煩多線程

直接聲明可選參數:app

//單例
    static let shared = ImageCache()
    //存儲圖片
    func storeImage(url:URL,image:UIImage?,toDisk:Bool?=nil) -> Void {
        let urlStr = "\(url)"
        memoryDic?.setValue(image, forKey:urlStr)
        if toDisk ?? false {
            //往硬盤裏存
            print("存硬盤")
        }
    }
//.  這裏的  ?=nil,該形參能夠選擇傳入,調用就能夠:
//            ImageCache.shared.storeImage(url: url, image: self.image!)
            ImageCache.shared.storeImage(url: url, image: self.image!, toDisk: true)

兩種均可以了直接用了 ,不用報錯。一個函數搞定,不用像OC那樣 多一個參數就要再寫一個方法。這樣寫可能有一些問題,可是慢慢使用才能體會到。 接下來就看看Swift 的 本地沙盒存儲操做語法函數

直接先把方括號改成點語法試試:url

//緩存類-------
//這裏不寫:繼承類,它默認會繼承什麼呢? Object?
class ImageCache {
    //聲明及初始化
    var memoryDic:NSMutableDictionary? = [:]
    //單例
    static let shared = ImageCache()
    //存儲圖片
    func storeImage(url:URL,image:UIImage?,toDisk:Bool?=nil) -> Void {
        let urlStr = "\(url)"
        memoryDic?.setValue(image, forKey:urlStr)
        if toDisk ?? false {
            //往硬盤裏存
            print("存硬盤")
            //先建立一個存儲文件夾,後面這個建立代碼寫到該類初始化的時候.注意路徑寫的時候斜槓
            let myDirectory:String = NSHomeDirectory() + "/Documents/ImageCache/"
            let fileManager = FileManager.default
            //withIntermediateDirectories爲ture表示路徑中間若是有不存在的文件夾都會建立
            try! fileManager.createDirectory(atPath: myDirectory,                                     withIntermediateDirectories: true, attributes: nil)
            //這裏路徑也作一下處理,文件名字作一下md5防止重複,這裏md5路徑寫法有點小問題,到時候參考Kingfisher的算法吧,不過md5自己算法沒問題,只是我用url字符串去作md5不知道穩當不穩當。
            let md5FileNamePath = myDirectory + urlStr.md5()
            fileManager.createFile(atPath: md5FileNamePath, contents: UIImageJPEGRepresentation(image!, 1.0), attributes: nil)
            
        }
    }
    //取圖片
    func imageForKey(url:URL,formDisk:Bool?=nil) ->UIImage? {
        let urlStr = "\(url)"
        //若是內存裏有 直接到內存裏拿去顯示
        if memoryDic?.allValues.count != 0 && memoryDic?.allValues.count != nil {
            let image:UIImage = memoryDic!.object(forKey: urlStr) as! UIImage
            return image
        }
        //若是內存裏沒有 再去硬盤裏找
//        image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:[self cachePathForKey:key]]];
        let myDirectory:String = NSHomeDirectory() + "/Documents/ImageCache/"
        let md5FileNamePath = myDirectory + urlStr.md5()
        let img = UIImage.init(contentsOfFile: md5FileNamePath)
        if (img != nil) {
            return img
        }
        return nil
    }
   
 }
 //md5

 String+MD5.swift

 import Foundation
extension String {
    func md5() -> String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)
        let hash = NSMutableString()
        for i in 0 ..< digestLen {
            hash.appendFormat("%02x", result[i])
        }
        result.deinitialize()

        return String(format: hash as String)
    }
}

#import <CommonCrypto/CommonDigest.h>

DIY_SFSCKingfisher-Bridging-Header.h

import Foundation
import UIKit
/// typealias用來爲已存在的類型從新定義名稱的。
typealias ImageView = UIImageView
extension ImageView {
    func sfsc_setImage(url:URL?) -> Void {
        //------- 這部分代碼,每一個須要網絡圖片的都會用到,因此提取出來 ---------
        /* guard let語法:guard let 判斷以後 守護 必定有值 若是沒有值 在guard let 的{} 裏 直接返回。
          若是須要守護多個值直接在後面跟 逗號 分割開來。
         
         */
        guard let url = url else {
            return
        }
        //代碼執行至此 url 必定有值!!
        if (ImageCache.shared.imageForKey(url: url) != nil) {
            //若是從內存緩存裏拿到值就直接顯示 而後直接返回,不去加載
            self.image = ImageCache.shared.imageForKey(url: url)
            return
        }
        
        //轉爲data類型
        let data : NSData! = NSData(contentsOf: url)
        //判斷data不爲空,這裏是由於swift對類型要求很嚴,若是未空的話,會崩潰
        if data != nil {
            //賦值圖片
            self.image = UIImage.init(data: data as Data, scale: 1)
//            ImageCache.shared.storeImage(url: url, image: self.image!)
            ImageCache.shared.storeImage(url: url, image: self.image!, toDisk: true)
        }else{
            // 不然就賦值默認圖片
            self.image = UIImage.init(named: "005")
        }
    }
}
相關文章
相關標籤/搜索