如何修复图片下载后UIImageView的Aspect Fit异常问题
嘿,这个问题我太熟了!本质就是UITableView的Cell高度缓存复用在搞事情——第一张图加载完后,Cell的高度被TableView缓存下来,后续加载的新图哪怕尺寸不一样,TableView也没及时重新计算高度,直接复用了旧高度,导致图片被错误裁剪。退出页面再返回相当于清空了缓存,所以问题就消失了。
下面给你几个亲测有效的解决办法:
方案一:加载完成后触发行高度刷新(简单直接)
在Kingfisher的图片加载回调里,手动让当前Cell所在的TableView重新计算对应行的高度,这样就能覆盖旧的缓存高度:
// 先给Cell加个weak属性存TableView,在cellForRowAt里赋值:cell.tableView = tableView weak var tableView: UITableView? // 图片加载代码改成这样 let mainImageUrl = URL(string: noteImage!.imageUrl) self.noteImageView.kf.indicatorType = .activity self.noteImageView.kf.setImage(with: mainImageUrl) { [weak self] result in guard let self = self else { return } // 获取当前Cell的indexPath,触发行高度刷新 if let indexPath = self.tableView?.indexPath(for: self) { // 用begin/endUpdates比直接reloadRows更平滑,不会有闪烁 self.tableView?.beginUpdates() self.tableView?.endUpdates() } }
方案二:优化自动高度的缓存逻辑
如果你的TableView用的是UITableView.automaticDimension,那得确保预估行高设置合理,同时避免错误缓存:
// 在ViewController的viewDidLoad里配置 tableView.estimatedRowHeight = 250 // 设一个和你图片平均高度接近的值,别设成0或者极端值 tableView.rowHeight = UITableView.automaticDimension
然后在Cell的图片加载完成后,强制更新ImageView的布局信息,让AutoLayout能正确计算高度:
self.noteImageView.kf.setImage(with: mainImageUrl) { [weak self] result in guard let self = self, case .success(let value) = result else { return } // 更新ImageView的固有尺寸,触发AutoLayout重算 self.noteImageView.intrinsicContentSize = value.image.size self.noteImageView.setNeedsLayout() self.noteImageView.layoutIfNeeded() }
方案三:自定义ImageView精准控制尺寸(彻底解决适配问题)
要是上面的方法还偶尔出问题,那就自定义一个UIImageView子类,重写intrinsicContentSize,让它严格按照aspect-fit的规则返回尺寸:
class AspectFitImageView: UIImageView { override var intrinsicContentSize: CGSize { guard let image = image else { return super.intrinsicContentSize } // 按照当前ImageView的宽度,计算aspect-fit后的高度 let widthRatio = bounds.width / image.size.width let targetHeight = image.size.height * widthRatio return CGSize(width: bounds.width, height: targetHeight) } override func layoutSubviews() { super.layoutSubviews() // 布局变化时强制更新固有尺寸 invalidateIntrinsicContentSize() } }
之后把Cell里的noteImageView换成这个子类,加载图片后调用invalidateIntrinsicContentSize(),AutoLayout就能精准算出Cell的正确高度了。
内容的提问来源于stack exchange,提问作者Keith
相关产品推荐
相关产品推荐

