title: How to asynchronously load images for UICollectionViewCell without reuse issues?
body: <p>Background of problem: I am using Kingfisher to download and set images for all of my collection views and table views in my app. This works well, but I have one specific use case that I'm pretty sure Kingfisher doesn't have built in.</p>
  
  <p>What I am trying to do: Download multiple images for a single collection view cell, and then update the cell with the images.</p>
  
  <p>Why I am not using <code>.kf.setImage(...)</code>: The collection view cell UI is all drawn from <code>draw(_ rect: CGRect)</code></p>
  
  <p>What I am doing now: In my <code>UICollectionViewCell</code> I have an image array</p>
  
  <pre class="lang-swift prettyprint-override"><code>var posters: [UIImage] = [] {
      didSet {
          setNeedsDisplay()
      }
  }
  </code></pre>
  
  <p>and I draw them into the cell</p>
  
  <pre class="lang-swift prettyprint-override"><code>context.draw(image, in: CGRect(x: 0, y: -posterWindowFrame.minY, width: actualPosterWidth, height: actualPosterHeight))
  </code></pre>
  
  <p>In my view controller I load images in <code>willDisplayCell:forItemAtIndexPath:</code> like so</p>
  
  <pre class="lang-swift prettyprint-override"><code>override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
          let imageProviders = viewModel.imageProviders(at: indexPath)
          var images = [UIImage]()
          let group = DispatchGroup()
          let cachedIndexPath = indexPath
          imageProviders.forEach { provider in
              guard let provider = provider else { return }
              group.enter()
              _ = KingfisherManager.shared.retrieveImage(with: .provider(provider), options: [.targetCache(posterCache)]) { result in
                  DispatchQueue.main.async {
                      defer {
                          group.leave()
                      }
                      switch result {
                      case .success(let imageResult):
                          images.append(imageResult.image)
                      case .failure:
                          print("No image available")
                      }
                  }
              }
          }
  
          group.notify(queue: .main) {
              guard
                  let cell = collectionView.cellForItem(at: cachedIndexPath) as? ListCollectionViewCell
                  else { return }
              cell.posters = images
          }
      }
  </code></pre>
  
  <p>This works, but I can see the images changing (which could probably be fixed by pre-fetching) but I also notice a lot of lag when scrolling that I don't see when I comment this function out. </p>
  
  <p>Besides fetching all of the images in <code>ViewDidLoad</code> (or anywhere else, because of API rate limiting), how can I load these images in a way that doesn't cause lag and won't have problems with cell reuse?</p>
  
  <p>EDIT - 8/13/19
  I used <code>UICollectionViewDataSourcePrefetching</code> to fetch the images and cache them locally, and then set the images in <code>cellForRow</code> and it seems to work well for now. </p>