前语
在源码解析的第一篇中,咱们讲解了 Kingfisher 的最主要的功能-异步加载网络图片的流程,以及怎么设计支撑同一个类型参数能够依据 URL 类型加载本地以及网络的资源。
第二篇中,咱们讲解了它怎么完成内存、磁盘双缓存以及缓存的详细配置参数。
这一篇咱们接着来依据 Features 继续整理代码。
Cancelable downloading and auto-reusing previous downloaded content to improve performance.
当咱们加载列表中的图片时,能够在 UITableView 或许 UICollectionView 的署理办法中直接对 cell 的 imageView 直接调用 setImage() 来异步加载网络资源。下面以 UICollectionView 为例子,写一下示例代码:
override func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "collectionViewCell",
for: indexPath) as! ImageCollectionViewCell
let url = ImageLoader.sampleImageURLs[indexPath.row]
cell.cellImageView.kf.setImage(with: url)
return cell
}
这样是完全能够完成咱们的需求的。但它也存在一个问题,那就是当你快速滑动的时候,当时屏幕加载的图片可能还未加载完就已经滑出屏幕了。也就是说你消耗的系统资源并不是百分百有用的,由于屏幕外的图片加载你也在执行,但这部分对用户来讲是无效的。咱们能够结合 Kingfisher 的撤销下载和预加载的功能来解决这个问题。
对应 UICollectionView 来说,咱们能够在 didEndDisplaying 的署理办法中撤销下载,在 willDisplay 的署理办法中预加载。示例代码如下:
override func collectionView(
_ collectionView: UICollectionView,
didEndDisplaying cell: UICollectionViewCell,
forItemAt indexPath: IndexPath) {
(cell as! ImageCollectionViewCell).cellImageView.kf.cancelDownloadTask()
}
override func collectionView(
_ collectionView: UICollectionView,
willDisplay cell: UICollectionViewCell,
forItemAt indexPath: IndexPath) {
let imageView = (cell as! ImageCollectionViewCell).cellImageView!
let url = ImageLoader.sampleImageURLs[indexPath.row]
KF.url(url).set(to: imageView)
}
Independent components. Use the downloader, caching system, and image processors separately as you need.

比方,在自己的项目中,经常会碰到一些数据缓存的功能。这时,你就能够独自运用它的缓存功能来完成,这样就不用自己再写一套缓存机制了。示例代码如下(以 String 为例):
extension String: CacheCostCalculable {
public var cacheCost: Int {
return Data(self.utf8).count
}
}
let totalMemory = ProcessInfo.processInfo.physicalMemory
let costLimit = totalMemory / 4
let memoryStorage = MemoryStorage.Backend<String>(config:
.init(totalCostLimit: (costLimit > Int.max) ? Int.max : Int(costLimit)))
memoryStorage.store(value: "测试数据", forKey: "test_key")
由于它要求存入的值遵守 CacheCostCalculable 协议以核算缓存的巨细,所以咱们需要给 String 的扩展中完成一下 cacheCost 核算特点。
之后的运用代码能够看出来,跟别的模块是没有什么耦合的。
Prefetching images and showing them from the cache to boost your app.
这一条跟上面的预加载是一个意思。
Extensions forUIImageView,NSImageView,NSButton,UIButton,NSTextAttachment,WKInterfaceImage,TVMonogramViewandCPListItemto directly set an image from a URL.
Kingfisher 不仅仅给 UIImageView 添加了扩展特点 kf,它还给按钮、文本等控件添加了扩展特点。源码如下:
extension KFCrossPlatformImage: KingfisherCompatible { }
extension KFCrossPlatformImageView: KingfisherCompatible { }
extension KFCrossPlatformButton: KingfisherCompatible { }
extension NSTextAttachment: KingfisherCompatible { }
Built-in transition animation when setting images.
Kingfisher 内部供给了许多过度动画,能够在网络资源加载完的时候展现,支撑类型如下:
public enum ImageTransition {
case none
case fade(TimeInterval)
case flipFromLeft(TimeInterval)
case flipFromRight(TimeInterval)
case flipFromTop(TimeInterval)
case flipFromBottom(TimeInterval)
case custom(duration: TimeInterval,
options: UIView.AnimationOptions,
animations: ((UIImageView, UIImage) -> Void)?,
completion: ((Bool) -> Void)?)
}
读源码能够看到,不仅支撑 5 中类型,还能够自定义自己想完成的类型。该功能对 UI 漂亮度要求高的 APP 开发者还是很有友好的。
动画的详细完成看源码能够知道,本质上是对 UIView.AnimationOptions 的一层封装:
var animationOptions: UIView.AnimationOptions {
switch self {
case .none: return []
case .fade: return .transitionCrossDissolve
case .flipFromLeft: return .transitionFlipFromLeft
case .flipFromRight: return .transitionFlipFromRight
case .flipFromTop: return .transitionFlipFromTop
case .flipFromBottom: return .transitionFlipFromBottom
case .custom(_, let options, _, _): return options
}
}
每个动画详细的效果图,大家能够运行一下官方的 Demo 看一下。详细的逻辑在这个控制器:TransitionViewController。
Customizable placeholder and indicator while loading images.
支撑自定义占位图和指示器。
public enum IndicatorType {
case none
case activity
case image(imageData: Data)
case custom(indicator: Indicator)
}
Extensible image processing and image format easily.
支撑多种图片格式,比方:PNG、JPEG、GIF等。概况可参考 官方的 Demo。
Low Data Mode support.
支撑在 Low Data Mode 的情况下,加载低分辨率的图片或许加载本地图片。
SwiftUI support.
Kingfisher 也适配了 SwiftUI,在你的 SwiftUI 项目中也能够运用它了。
示例代码如下 – KFImage:
var body: some View {
HStack(alignment: .center) {
Spacer()
KFImage.url(url)
.resizable()
Spacer()
}.padding(.vertical, 12)
}
到这里。Kingfisher 的源码阅览就全部完成了,如果本系列文章有哪里写的不对的当地,还请读者指正。
