James
James

Reputation: 1

Hiding UIImageView in UICollectionViewCell when Kingfisher download fails in Swift

I want to hide my UIImageView in UICollectionViewCell and update cell size when Kingfisher download fails.

My setData function called in 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
                // the above line is not enough I should also update cell size this is the my actual problem.
            }
        }
    } else {
        self.newsImageView.isHidden = true
    }
    
}

CellForItem

        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.swift

    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()
    }
}

Upvotes: 0

Views: 298

Answers (1)

Drew
Drew

Reputation: 739

You should move your setData call to occur directly in cellForItemAt. Then in the callback, you can hide the image view (like you're doing). Then immediately after that in the callback, call collectionView.reconfigureItems(at:) (if using iOS 15+) or collectionView.reloadItems(at:)

You'll likely need to implement a bool flag on the cell (or possibly the article itself) for when the image can't be loaded. Otherwise you may get into an infinite loop of reloading the cell when it reloads.

Upvotes: 0

Related Questions