You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中Kingfisher下载失败时隐藏UIImageView并更新UICollectionViewCell尺寸

问题描述

实现Kingfisher下载图片失败时,隐藏UICollectionViewCell中的UIImageView,同时自动更新对应单元格的尺寸。

现有代码

setData方法(cellForItem中调用)

func setData(with data: Article?, indexPath: IndexPath) {
    guard let data = data else { return }
    
    if let imageUrl = data.urlToImage, imageUrl.isValidURL, let url = URL(string: imageUrl.addingPercentEncoding) {
        self.newsImageView.kf.setImage(with: url, options: [.transition(.fade(0.3))]) { [weak self] result in
            guard let self = self else { return }
            switch result {
            case .success(_):
                self.newsImageView.isHidden = false
            case .failure(let error):
                self.newsImageView.isHidden = true
                // 仅隐藏图片无法满足需求,需要同步更新单元格尺寸
            }
        }
    } else {
        self.newsImageView.isHidden = true
    }
    
}

collectionView(_:cellForItemAt:)代理实现

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let homeCell = collectionView.dequeueReusableCell(withReuseIdentifier: HomeCollectionViewCell.identifier, for: indexPath) as? HomeCollectionViewCell,
          let article = viewModel.getArticle(at: indexPath)
    
    else {
        let emptyCell = collectionView.dequeueReusableCell(withReuseIdentifier: EmptyArticlesCollectionViewCell.identifier, for: indexPath)
        return emptyCell
    }
    
    homeCell.configure(with: article, indexPath: indexPath)
    return homeCell
}

HomeCollectionViewCell相关实现

class HomeCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var homeCollectionViewCellComponent: HomeCollectionViewCellComponent!
    
.
.
.

    func configure(with data: Article, indexPath: IndexPath) {
        homeCollectionViewCellComponent.setData(with: data, indexPath: indexPath)
    }
    
    override func prepareForReuse() {
        homeCollectionViewCellComponent.prepareForReuse()
    }
}
实现方案

按以下步骤调整即可:

  • 先在数据层加状态标记,不要把图片加载成功/失败的状态仅存在cell内部。给Article模型新增布尔属性hasValidImage,初始化时如果存在合法图片URL就默认设为true,无有效URL则设为false。
  • 调整Kingfisher加载回调逻辑:加载成功时将对应位置数据的hasValidImage设为true,加载失败时设为false,不要只修改cell的isHidden属性就结束。
  • 配置自适应约束:把newsImageView的高度约束拖成属性,当hasValidImage为true时使用正常图片高度(比如按屏宽16:9比例计算),为false时将高度约束值改为0;其余控件的垂直约束要依次衔接,图片高度为0时整个cell的内容高度会自动收缩。
  • 在collectionView(_:layout:sizeForItemAt:)代理方法中,直接读取对应位置Article模型的hasValidImage状态计算返回尺寸,不要从已加载的cell中取状态计算,避免复用错位。
  • 图片加载回调中更新完模型状态后,在主线程调用performBatchUpdates刷新对应位置的cell即可,不要全量调用reloadData(),避免列表闪烁:
DispatchQueue.main.async {
    collectionView.performBatchUpdates({
        collectionView.reloadItems(at: [indexPath])
    })
}
  • 补充复用逻辑:在prepareForReuse方法里把newsImageView的高度约束重置为默认值,同时重置图片的显示状态,避免cell复用时出现布局错乱。

注意:不要在cell内部持有indexPath做逻辑判断,cell复用过程中indexPath会动态变化,很容易读错对应数据,所有和单元格相关的状态统一从ViewModel/Model层读取是最稳妥的方案。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:09:20