使用Kingfisher实现图片逐帧缓存并循环复用缓存资源的问题
解决方案
要实现首次加载图片后循环复用缓存、无需重复发起网络请求的需求,你可以通过调整Kingfisher的配置选项+优化预加载逻辑来实现:
1. 配置Kingfisher缓存策略
修改UIImageView扩展的setImage方法,添加缓存优先的核心配置,确保优先读取本地缓存,仅在缓存不存在时才发起网络请求:
extension UIImageView { func setImage(imageUrl: String, completion: (() -> ())? = nil) { guard let url = URL(string: imageUrl) else { completion?() return } let options: KingfisherOptionsInfo = [ .alsoPrefetchToMemory, // 核心:优先用缓存,无缓存再请求网络 .cachePolicy(.returnCacheDataElseLoad), // 确保图片缓存到磁盘,App重启后仍可复用 .cacheOriginalImage ] self.kf.setImage(with: url, options: options) { _ in completion?() } } }
.cachePolicy(.returnCacheDataElseLoad):强制Kingfisher先检查内存+磁盘缓存,存在则直接复用,不存在才发起网络请求。.cacheOriginalImage:保证原始图片被持久化到磁盘缓存,避免App重启后需要重新加载。.alsoPrefetchToMemory:保留该选项,将图片预加载到内存缓存,切换时读取速度更快。
2. 首次加载时批量预加载所有图片
为了让首次循环时所有图片都已缓存完成,避免切换过程中仍有网络请求,可在configureView中添加批量预加载逻辑:
func configureView(images: ApiImages) { guard let images = images.images else { return } imagesArray = images imagesCount = images.count // 批量预加载所有图片到缓存 let imageURLs = images.compactMap { URL(string: $0) } ImagePrefetcher(urls: imageURLs).start() // 启动第一张图展示与动画 imageView.setImage(imageUrl: images[nextImage]) nextImage += 1 animateImage() }
使用ImagePrefetcher可以一次性将所有图片预加载到缓存,首次循环过程中后续图片已提前缓存完成,切换时直接读取缓存即可。
3. 优化动画冲突问题(可选)
你的UIView过渡动画时长是0.1秒,而原代码中Kingfisher自带0.5秒的过渡动画,两者会导致动画效果异常。建议移除Kingfisher的过渡动画,统一使用UIView的动画逻辑:
// 扩展中移除.transition(.fade(0.5))选项 extension UIImageView { func setImage(imageUrl: String, completion: (() -> ())? = nil) { guard let url = URL(string: imageUrl) else { completion?() return } let options: KingfisherOptionsInfo = [ .alsoPrefetchToMemory, .cachePolicy(.returnCacheDataElseLoad), .cacheOriginalImage ] self.kf.setImage(with: url, options: options) { _ in completion?() } } }
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

