目錄
一、使用方式:
二、下載下傳原理:
三、請求設定:
請求的預設設定方式通過上面的單例設定,單獨每個請求的設定可以通過
四、緩存機制
五、下載下傳設定
今年到新公司,發現公司用的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
更改逾時時間
三、請求設定:
-
請求的預設設定方式通過上面的單例設定,單獨每個請求的設定可以通過
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
}