Swift中无需传入URL如何为UIImage使用Kingfisher加载图片?
问题排查与解决方案
你当前代码的核心问题
你现在的用法完全没有用到Kingfisher的能力,反而会触发Cell复用异常:
cell.profileImage.kf.base.image = image和直接写cell.profileImage.image = image没有任何区别,kf.base本质就是UIImageView本身- 自定义异步回调
getProfileImage返回时,当前Cell很可能已经被复用来展示其他行的数据,直接赋值就会出现图片乱跳、显示错误的问题,这也是你运行异常的核心原因。
无需URL也可以使用Kingfisher
Kingfisher专门提供了非URL资源的接入接口,你可以直接把已拿到的UIImage对象封装成Kingfisher可识别的资源,享受Kingfisher的复用校验、自动缓存、加载动画等全部能力,不需要自己处理复用逻辑。
修复方案
方案1:快速适配现有逻辑
如果你的getProfileImage已经有成熟的内部缓存逻辑,只需要解决复用问题,直接用RawImageProvider封装拿到的图片即可:
let employee = directoryPresenter!.getEmployeeItem(position: indexPath.row) let empId = employee.employeeID // 先设置占位图避免空白 cell.profileImage.image = UIImage(named: "default_avatar") directoryPresenter!.getProfileImage(id: empId) { [weak cell] image in guard let cell = cell, let image = image else { return } cell.profileImage.kf.setImage( with: .provider(RawImageProvider(image: image, cacheKey: "profile_\(empId)")), placeholder: UIImage(named: "default_avatar") ) }
这个方案里Kingfisher会自动校验当前Cell是否还对应原来的员工ID,不会出现复用错乱的问题,同时这张图片会被存入Kingfisher的缓存,后续再用到可以直接读取,不需要重复走getProfileImage逻辑。
方案2:全逻辑托管给Kingfisher
如果希望把图片加载、缓存的逻辑全部交给Kingfisher管理,可以自定义符合ImageDataProvider协议的资源提供者:
// 自定义头像资源提供者 struct EmployeeAvatarProvider: ImageDataProvider { let employeeID: String // 缓存Key和员工ID绑定,保证全局唯一 var cacheKey: String { "profile_\(employeeID)" } func data(handler: @escaping (Result<Data, Error>) -> Void) { directoryPresenter?.getProfileImage(id: employeeID) { image in guard let image = image, let pngData = image.pngData() else { handler(.failure(NSError(domain: "AvatarLoadError", code: -1, userInfo: nil))) return } handler(.success(pngData)) } } } // Cell赋值处直接调用即可 let employee = directoryPresenter!.getEmployeeItem(position: indexPath.row) cell.profileImage.kf.setImage( with: EmployeeAvatarProvider(employeeID: employee.employeeID), placeholder: UIImage(named: "default_avatar") )
内容的提问来源于stack exchange,提问作者Thejani Saranaguptha
相关产品推荐
相关产品推荐

