如何使用SDWebImage调整缓存图片大小及预处理云端图片?
解决方案
核心思路
要实现缓存图片更新为新尺寸、云端图片先调整再存缓存,关键在于自定义缓存KEY(结合目标尺寸区分不同版本的缓存),同时配合图片转换逻辑。
1. 更新已有缓存的图片为新尺寸
步骤:
- 从SDImageCache中通过原URL的KEY取出旧图片
- 调整图片到目标尺寸
- 用原KEY替换缓存(或用新KEY保留原尺寸缓存)
代码示例:
// 目标尺寸,根据需求修改 let targetSize = CGSize(width: 200, height: 200) // 原图片的URL guard let originalURL = NSURL.sd_URL(with: ref) as URL? else { return } let originalCacheKey = originalURL.absoluteString // 1. 从缓存获取原图片 SDImageCache.shared.queryImage(forKey: originalCacheKey) { [weak self] originalImage, _, _ in guard let image = originalImage else { print("原图片不在缓存中") return } // 2. 使用SDWebImage的转换器调整尺寸(或自定义缩放方法) let resizingTransformer = SDImageResizingTransformer(size: targetSize, scaleMode: .aspectFill) guard let resizedImage = resizingTransformer.transform(image, for: originalURL) else { return } // 3. 更新缓存:二选一 // 选项A:替换原缓存的图片(原尺寸图片会被覆盖) SDImageCache.shared.store(resizedImage, forKey: originalCacheKey, completion: { print("缓存已更新为新尺寸") }) // 选项B:用新KEY存储(保留原尺寸缓存,新尺寸存为独立条目) // let newCacheKey = "\(originalCacheKey)_\(targetSize.width)x\(targetSize.height)" // SDImageCache.shared.store(resizedImage, forKey: newCacheKey, completion: nil) }
2. 加载云端图片时先调整尺寸再存缓存
步骤:
- 自定义缓存KEY(结合尺寸),确保转换后的图片存入对应KEY
- 使用SDImageResizingTransformer在下载后自动调整尺寸
- 让SDWebImage自动存储转换后的图片(或手动存储)
代码示例:
方式一:自定义缓存KEY过滤器(推荐)
通过自定义SDImageCacheKeyFilter,自动根据目标尺寸生成唯一缓存KEY:
// 自定义KEY过滤器,根据URL+尺寸生成缓存KEY class SizeAwareCacheKeyFilter: SDImageCacheKeyFilter { func cacheKey(for url: URL, context: [SDWebImageContextOption : Any]?) -> String? { guard let targetSize = context?[.customTargetSize] as? CGSize else { return url.absoluteString } // 拼接尺寸信息到KEY中 let sizeSuffix = String(format: "%.0fx%.0f", targetSize.width, targetSize.height) return "\(url.absoluteString)_\(sizeSuffix)" } } // 使用时: let targetSize = CGSize(width: 200, height: 200) // 配置全局缓存的KEY过滤器 SDImageCache.shared.cacheKeyFilter = SizeAwareCacheKeyFilter() // 初始化图片管理器 let manager = SDWebImageManager(cache: SDImageCache.shared, loader: StorageImageLoader.shared) // 创建尺寸转换器 let resizingTransformer = SDImageResizingTransformer(size: targetSize, scaleMode: .aspectFill) // 加载图片 manager.loadImage(with: NSURL.sd_URL(with: ref) as URL?, options: [.transformDownloadedImage], // 开启下载后自动转换 context: [ .imageTransformer: resizingTransformer, .customTargetSize: targetSize // 传递尺寸给KEY过滤器 ], progress: nil) { image, _, error, _, _, _ in if let resizedImage = image { print("图片已调整尺寸并自动存入缓存") } }
方式二:手动存储转换后的图片
如果不想全局修改缓存KEY过滤器,可以手动生成KEY并存储:
let targetSize = CGSize(width: 200, height: 200) guard let url = NSURL.sd_URL(with: ref) as URL? else { return } // 生成带尺寸的缓存KEY let customCacheKey = "\(url.absoluteString)_\(targetSize.width)x\(targetSize.height)" let manager = SDWebImageManager(cache: SDImageCache.shared, loader: StorageImageLoader.shared) let resizingTransformer = SDImageResizingTransformer(size: targetSize, scaleMode: .aspectFill) manager.loadImage(with: url, options: [], context: [.imageTransformer: resizingTransformer], progress: nil) { [weak self] image, _, error, _, _, _ in guard let resizedImage = image else { return } // 手动存入自定义KEY的缓存 SDImageCache.shared.store(resizedImage, forKey: customCacheKey, completion: { print("调整后的图片已存入缓存") }) }
关于缓存KEY的说明
之前Stack Overflow方案失效的核心原因是没有用尺寸区分缓存KEY:
- SDWebImage默认用URL的绝对字符串作为缓存KEY,不同尺寸的图片如果用同一个KEY,会导致缓存覆盖或读取错误
- 必须在KEY中加入尺寸标识(如
200x200),让不同尺寸的图片拥有独立的缓存条目,这样才能正确更新和读取对应尺寸的缓存
内容的提问来源于stack exchange,提问作者Icare
相关产品推荐
相关产品推荐

