skip to Main Content

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


  1. add cell.layoutIfNeeded() before returning cell.

    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])
        cell.layoutIfNeeded()
        return cell
    }
    
    Login or Signup to reply.
  2. try postImageView.sd_cancelCurrentImageLoad() in your prepareForReuse()

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search