Search code examples
swiftuiimageviewkingfisher

Kingfisher download multiple images with custom image view


I would like to download multiple images with kingfisher and display those on collection view with page control (like instagram home feed). To do that I created custom image view. I tried like below but images being shown are all the same even though urls are different. How can I fix this? Thank you in advance!

import UIKit
import Kingfisher

class CustomImageView: UIImageView {

    var lastUrlToLoad: String?

    func loadMultipleImages(urlStrings: [String]) {

        for urlString in urlStrings {

            lastUrlToLoad = urlString
            guard let url = URL(string: urlString) else { return }
            let resouce = ImageResource(downloadURL: url, cacheKey: urlString)

            KingfisherManager.shared.retrieveImage(with: resouce, options: nil, progressBlock: nil) { [weak self] (img, err, type, url) in
                if err != nil {
                    return
                }

                if url?.absoluteString != self?.lastUrlToLoad {
                    return
                }

                DispatchQueue.main.async {
                    self?.image = img
                }
            }
        }
    }
}

Edit

I use this method like so.

class CollectionView: UICollectionViewCell {

    @IBOutlet var imageView: CustomImageView!

     var post: Post? {
         didSet {
             guard let urlStrings = post?.imageUrls else { return }
             imageView.loadMultipleImages(urlStrings: urlStrings)
         }
     }
 }

Solution

  • The problem is that you are trying to display multiple images in a single image view. As a result, all images are downloaded but only last retrieved image is being displayed. You probably want to have some collection view with photos where:

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageUrls.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        //dequeueReusableCell with imageView
    
        cell.imageView.kf.setImage(with: imageUrls[indexPath.row])
    
        return cell
    }
    

    Optionally you could conform to UICollectionViewDataSourcePrefetching to add image prefetching, which is also supported by Kingfisher:

    collectionView.prefetchDataSource = self
    
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        ImagePrefetcher(urls: indexPaths.map { imageUrls[$0.row] }).start()
    }