2

I am having trouble finding a good example of how I can cache images in a table view using URLSession to get image from the internet (API).

However, I am getting issues with the cache - Here is my code so far:

func configure(with urlString: String, name: String, address: String, station: String) {
    
    var imageCache = NSCache<UIImage, String>()
    
    loader.startAnimating()
    loader.isHidden = false
    
    guard let url = URL(string: urlString) else {
        return
    }
    
    let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
        guard let data = data, error == nil else {
            return
        }
        
        let locationImage = UIImage(data: data)
        
        imageCache.setObject(locationImage!, forKey: urlString)
        
        imageCache[url] = locationImage
        
        DispatchQueue.main.async {
            self?.nameLabel.text = name
            self?.addressLabel.text = address
            self?.locationImageView.image = locationImage
            self?.loader.stopAnimating()
            self?.loader.isHidden = true
        }
    }
    task.resume()
}

screnshot of code

errors include:

Cannot convert value of type 'String' to expected argument type 'UIImage' Value of type 'NSCache<UIImage, AnyObject>' has no subscripts 'NSCache' requires that 'String' be a class type

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
jo1
  • 115
  • 1
  • 12
  • Also, if the `configure` method is part of the table view cell class, then you're not instantiating the cache at the proper place. And you should also take care regarding the http request, as you don't want to end up in situations where a reused cell gets populated with contents from an incorrect cell. – Cristik Sep 26 '21 at 13:26
  • yes this is the issue i was getting also - i have contents in incorrect cells - how can i address this? where should instantiate the cache ? – jo1 Sep 27 '21 at 18:23
  • i moved this outside the configure method is this okay or should i do this directly in the cell (cellforrow) at method @cristik ? – jo1 Sep 27 '21 at 19:56

1 Answers1

3

The statement

var imageCache = NSCache<UIImage, String>()

creates a cache where the key type is UIImage and the objects stored in the cache are Strings. You want it to be the other way round with one caveat: NSCache doesn't support String for the key type, it has to be NSString:

var imageCache = NSCache<NSString, UIImage>()

That way you'll be able to put UIImages into the cache while identifying them by URL strings.

Check out my demo project on GitHub: https://github.com/vadimbelyaev/ImagesCache

Vadim Belyaev
  • 2,456
  • 2
  • 18
  • 23
  • I managed to find a nice and easy solution to caching images - kingfisher install on cocopods – jo1 Dec 27 '21 at 17:14
  • Yes, there are many libraries that would do image loading and caching: Kingfisher, SDWebImage, Nuke to name a few. But sometimes you just need a simple solution that you can implement in one short class that uses NSCache instead of adding a fairly complex 3rd party dependency to the project. – Vadim Belyaev Jan 06 '22 at 15:16