I found some similar questions but none of them worked for me. I have a UICollectionView acting as a feed with posts that can contain images. I fetch all the information (images included) from Firebase and when refreshing or scrolling up/down the collection, images change from one cell to another. I know this is for downloading the image & delays but I’m using SDWebImage already and tried prepareForReuse but none of this worked. Here’s some code:
class HomeViewController: UICollectionViewController {
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: homeImageTextCellReuseIdentifier, for: indexPath) as! HomeImageTextCell
cell.delegate = self
//Here I have the information with the URL image downloaded from FB
cell.viewModel = PostViewModel(post: posts[indexPath.row])
return cell
}
}
The HomeImageTextCell is a UICollectionViewCell with a collectionView inside to display the images, posts can have more than one to display. Inside this cell:
class HomeImageTextCell: UICollectionViewCell {
private let collectionView: UICollectionView = { ... }
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier!, for: indexPath) as! ImageCollectionViewCell
cell.viewModel = PostImageViewModel(imageString: imagesToDisplay[indexPath.row])
return cell
}
}
And finally, the ImageCollectionViewCell just has an image to display the image fetched from Firebase. This cell is the one that gets messy:
class ImageCollectionViewCell: UICollectionViewCell {
var viewModel: PostImageViewModel? {
didSet {
configure()
}
}
//MARK: - Properties
lazy var postImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFit
iv.clipsToBounds = true
return iv
}()
//MARK: - Lifecycle
override func prepareForReuse() {
super.prepareForReuse()
self.postImageView.isHidden = true
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(postImageView)
postImageView.anchor(top: topAnchor, left: leftAnchor, right: rightAnchor)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure() {
guard let viewModel = viewModel else { return }
postImageView.sd_setImage(with: viewModel.imageToDisplay, placeholderImage: UIImage())
}
}
2
Answers
add
cell.layoutIfNeeded()
before returning cell.try
postImageView.sd_cancelCurrentImageLoad()
in yourprepareForReuse()