天天看點

swift kingfisher原理使用 一、使用方式:二、下載下傳原理:三、請求設定:四、緩存機制五、下載下傳設定

目錄

 一、使用方式:

二、下載下傳原理:

三、請求設定:

請求的預設設定方式通過上面的單例設定,單獨每個請求的設定可以通過

四、緩存機制

五、下載下傳設定

今年到新公司,發現公司用的kingfisher這個第三方庫,和SDWebImage很類似,不過是swift版本的,就了解了下。

源碼位址: https://github.com/onevcat/Kingfisher

我看的是swift4.0最新版

 一、使用方式:

通過KingfisherManager單例對象調用。因為swift3以後大部分第三方調用普遍采用點方式,這個亦不例外,可以直接.kf調用單例。封裝方式:

public final class Kingfisher<Base> {
    public let base: Base
    public init(_ base: Base) {
        self.base = base
    }
}

public protocol KingfisherCompatible {
    associatedtype CompatibleType
    var kf: CompatibleType { get }
}

public extension KingfisherCompatible {
    public var kf: Kingfisher<Self> {
        return Kingfisher(self)
    }
}

extension Image: KingfisherCompatible { }

extension ImageView: KingfisherCompatible { }
extension Button: KingfisherCompatible { }
           

 這樣就可以實作image、Imageview、button的.kf調用,并且通過kf.base通路調用的對象實作封裝。

通過擴充extension Kingfisher where Base: ImageView {}實作每個對象的自定義方法,方法内部self.base即目前imageView。

let url = URL.init(string: newValue)
 self.imageView.kf.setImage(with: url)
           

基于kf作者imageView封裝過後可以直接調用

二、下載下傳原理:

KF是基于URLSession、URLSessionDelegate進行封裝的,請求預設屬性可以在appdeleget初始化是單例更改。例如:

KingfisherManager.shared.downloader.downloadTimeout = 12.0
           

更改逾時時間

三、請求設定:

  1. 請求的預設設定方式通過上面的單例設定,單獨每個請求的設定可以通過

retrieveImage(with resource: Resource,
        options: KingfisherOptionsInfo?,
        progressBlock: DownloadProgressBlock?,
        completionHandler: CompletionHandler?) -> RetrieveImageTask
           

單例方法調用的options設定,此外kf作者封裝的也可以直接傳參。

KingfisherOptionsInfo介紹:

  • case targetCache(ImageCache)//系統緩存位置。可以設定的屬性
  • case originalCache(ImageCache)//系統緩存原始圖像位置(隻用于自己設定placeholder) 
  • case downloader(ImageDownloader)//擷取更改session屬性,設定請求
  • case transition(ImageTransition)//自定義動畫
  • case downloadPriority(Float)//下載下傳優先級(0-1)
  • case forceRefresh //每次請求忽略緩存,直接下載下傳
  • case fromMemoryCacheOrRefresh//先取緩存再去檔案,再去下載下傳
  • forceTransition. //強制移動
  • cacheMemoryOnly  //隻從緩存讀取,不讀取本機沙盒圖檔
  • onlyFromCache//從緩存、沙盒讀取,沒有也不下載下傳網絡,顯示placeholder
  • backgroundDecode//設定後,顯示前在背景線程解碼
  • case scaleFactor(CGFloat)。//自定義圖檔data -> Image縮放比例,不指定按螢幕2x\3x縮放
  • preloadAllAnimationData預先加載data成圖檔緩存
  • case requestModifier(ImageDownloadRequestModifier)//改變請求 func modified(for request: URLRequest) -> URLRequest?  //手動更改單個請求逾時時間等一系列屬性
  • case processor(ImageProcessor)//自定義da ta轉圖檔樣式
  • case cacheSerializer(CacheSerializer)//自定義緩存data 轉圖像樣式
  • case keepCurrentImageWhileLoading //包含這個意味着placeHolder設定無效,沒有直接用預設
  • case onlyLoadFirstFrame。//如果傳回結果是.gif圖,隻取第一幀顯示
  • cacheOriginalImage //設定後,同時緩存原始圖檔和下載下傳後的圖檔
  • case callbackDispatchQueue(DispatchQueue?)。//自定義回掉隊列,不設定預設主線程

四、緩存機制

緩存處理主要在ImageCache類裡面

kf緩存和sdwebimage一緻,預設存儲在domain檔案夾,都是下載下傳下來存在緩存和沙盒裡面。下載下傳時先去緩存取,取不到取沙盒取,沙盒取不到去網絡下載下傳

此外,kf裡面,每次進入背景都會删除一周以前的圖檔(預設一周),然後檔案按存儲日期排序,删除到自定義最大沙盒存儲量的一半(預設無限制)

可以更改的屬性(更改方式參考二三部分):

maxMemoryCost //最大緩存量(預設無限制,收到記憶體警告直接清空)

pathExtension   //沙盒後續拼接檔案夾名稱

maxCachePeriodInSecond. //清除多久前的圖檔,預設一周

maxDiskCacheSize //沙盒最大存儲量,小于等于0表示無限制。預設無限制

五、下載下傳設定

ImageDownloader這個檔案裡面(設定參考二三部分)

downloadTimeout. //逾時時間

trustedHosts。//信任的請求位址,和自己實作請求代理設定沖突,二選一

sessionConfiguration。//session配置設定

requestsUsePipelining //請求是否管道類型,是否按順序下載下傳,第一個下載下傳完成在下載下傳下張圖檔。預設false

delegate. //下載下傳代理,kf已經封裝在請求代碼塊裡面,也可以自己全局代理封裝處理

authenticationChallengeResponder //信任請求代理,和trustedHosts沖突二選一

fetchLoads //下載下傳完成每個URL可能有多個處理方式,優先取這裡的。

六、其他

kf内圖檔處理挺好的,這裡注釋下部分方式,喜歡的可以自己去看下,在Image.swift檔案裡

1、擴充類存儲屬性,黑魔法:

fileprivate(set) var animatedImageData: Data? {
        get {
            return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
        }
        set {
            objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
           

2、public var normalized: Image   //傳回調整後的圖檔

3、static func animated(with data: Data, scale: CGFloat = 1.0, duration: TimeInterval = 0.0, preloadAll: Bool, onlyFirstFrame: Bool = false) -> Image?   //GIF圖data 轉圖檔

4、static func image(data: Data, scale: CGFloat, preloadAllAnimationData: Bool, onlyFirstFrame: Bool) -> Image? //根據data生成圖檔,GIF圖根據preloadAllAnimationData是否展示所有動畫圖檔,onlyFirstFrame:是否隻取GIF第一張圖檔 ,有調用上面的方法

5、public func image(withBlendMode blendMode: CGBlendMode,  alpha: CGFloat = 1, backgroundColor: Color? = nil)-> Image。   //根據blendMode、透明度、背景色 調整圖檔

6、public func image(withRoundRadius radius: CGFloat,  fit size: CGSize, roundingCorners corners: RectCorner = .all, backgroundColor: Color? = nil) -> Image 切換到指定角度、大小、背景色

7、    public func resize(to size: CGSize) -> Image //改變圖檔大小

8、    public func resize(to size: CGSize, for contentMode: ContentMode) -> Image。//根據ContentMode和目标size更改圖檔大小。//aspectFit: 根據圖檔比縮小到size   // aspectFill:根據圖檔比放大到size

9、public func crop(to size: CGSize, anchorOn anchor: CGPoint) -> Image //固定瞄點,縮小圖檔到指定size

10、public func blurred(withRadius radius: CGFloat) -> Image//根據角度模糊處理圖檔

11、public func overlaying(with color: Color, fraction: CGFloat) -> Image//圖檔添加overlay覆寫色fraction覆寫透明度

12、public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image//圖檔亮度、飽和度、對比度修改 kCIInputEVKey不知道這個對應什麼描述,喜歡的可以自己看下效果。

13、public func scaled(to scale: CGFloat) -> Image//縮放‘

14、

//圖檔格式确定。根據前8個位元組對比圖檔類型
    var imageFormat: ImageFormat {
        var buffer = [UInt8](repeating: 0, count: 8)
        (base as NSData).getBytes(&buffer, length: 8)
        if buffer == ImageHeaderData.PNG {
            return .PNG
        } else if buffer[0] == ImageHeaderData.JPEG_SOI[0] &&
            buffer[1] == ImageHeaderData.JPEG_SOI[1] &&
            buffer[2] == ImageHeaderData.JPEG_IF[0]
        {
            return .JPEG
        } else if buffer[0] == ImageHeaderData.GIF[0] &&
            buffer[1] == ImageHeaderData.GIF[1] &&
            buffer[2] == ImageHeaderData.GIF[2]
        {
            return .GIF
        }

        return .unknown
    }