10

I'm having a UICollectionView that holds pictures as elements in its datastore.

I want to load a high resolution pic into the element only when its corresponding UICollectionViewCell is currently showing on screen. Later, when the UICollectionViewCell goes off screen, I want to return the element's UIImage into the low resolution version.

My question is, how can I detect when a UICollectionViewCell is going off screen?

(I tried using the prepareForReuse method but I can't predict when it will be called).

I'm currently using a piece of code that sits in scrollViewDidScroll, and every time that the view scrolls I'm checking the self.collectionView.visibleCells to see which cells has scrolled off screen.

It seems a bit of an overhead and I wonder if there is a method called on the UICollectionViewCell itself whenever it is being scrolled of screen ?

KyleFarris
  • 16,408
  • 4
  • 40
  • 40
Boaz Saragossi
  • 908
  • 10
  • 30

3 Answers3

28

The collectionView:didEndDisplayingCell:forItemAtIndexPath: method on UICollectionViewDelegate should do what you want.

Mike Weller
  • 44,483
  • 14
  • 126
  • 148
4

From Documentation. collectionView:didEndDisplayingCell is called right after it finishes displaying, not when it goes off screen

Use this method to detect when a cell is removed from a collection view, as opposed to monitoring the view itself to see when it disappears

-1

collectionView:didEndDisplayingCell:forItemAtIndexPath: is the correct method to detect when a cell has gone from screen.

Meanwhile, I think it's more correct not to perform cleanup in collectionView:didEndDisplayingCell:forItemAtIndexPath: but to tell your cell to perform cleanup itself:

  func collectionView(_ collectionView: UICollectionView,
                 didEndDisplaying cell: UICollectionViewCell,
                   forItemAt indexPath: IndexPath) {
    cell.prepareForReuse()
  }

With this approach your UICollectionViewDelegate doesn't have to know any implementation details of your UICollectionViewCell subclass. In the cell we'll override prepareForReuse method:

 override func prepareForReuse() {
    super.prepareForReuse()

    imageView.image = lowResolutionImage
    highResolutionImage = nil
 }
Legonaftik
  • 1,156
  • 1
  • 14
  • 28
  • prepareForReuse() is called by the framework before a cell is dequeued with dequeueReusableCell(...). I recon that in you case you could clean up before reuse but that keeps the memory allocated until the cell has to be reused. If you want to accommodate memory issues the correct solution will be to deallocate your memory when the cell ends displaying. – esbenr Mar 15 '19 at 08:50