前语
在源码解析的第一篇中,咱们讲解了 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.
通过项目源码的文件分层咱们也能够看出来,Kingfisher 的模块设计做的是非常好的。它的资源加载、缓存或许图片处理器都是能够独自运用的。不一定非得全套运用。
比方,在自己的项目中,经常会碰到一些数据缓存的功能。这时,你就能够独自运用它的缓存功能来完成,这样就不用自己再写一套缓存机制了。示例代码如下(以 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
,TVMonogramView
andCPListItem
to 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 的源码阅览就全部完成了,如果本系列文章有哪里写的不对的当地,还请读者指正。