Upload image url to collectionView: UICollectionView, cellForItemAt indexPath: IndexPath delegate - ASYNCHRONOUSLY
Create a class with a shared instance
First cache the image Data relative to the key URL of the image
Why do we need to cache data?
Because - when scrolling, we donβt need to load Image Every Time, therefore Cache already loaded Image Data and returned cache data
I created a class name: AsyncImageLoader , then I created a function that is a completion handler that returns data after the image has finished loading
class AsyncImageLoader { //For caching the Image Data use NSCache var cache = NSCache<AnyObject, AnyObject>() //Shared Instance class var sharedLoader : AsyncImageLoader { struct Static { static let instance : AsyncImageLoader = AsyncImageLoader() } return Static.instance } //Completion handler function which returns the Image after complete downloading Image func imageForUrl(urlString: String, completionHandler: @escaping (_ image: UIImage?, _ url: String) -> ()) { let data = self.cache.object(forKey: urlString as AnyObject) as? NSData if let goodData = data { //check already we cached the image before or not let image = UIImage(data: goodData as Data) DispatchQueue.main.async(execute: {() in completionHandler(image, urlString) }) return } //if url Str is nil - check it or it crashes if urlString.characters.count <= 0 { DispatchQueue.main.async(execute: {() in completionHandler(nil, urlString) // returns nil }) return } let strToUrl = URL(string: urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)! URLSession.shared.dataTask(with: strToUrl, completionHandler: { (data, response, error) -> Void in if error == nil{ let image = UIImage(data: data!) self.cache.setObject(data as AnyObject, forKey: urlString as AnyObject) //setting cache of image with key as Image url DispatchQueue.main.async(execute: {() in completionHandler(image, urlString) //completion handler call }) } else { let image = UIImage(named: "logoBlue") //return dummy image if fails DispatchQueue.main.async(execute: {() in completionHandler(image, urlString) }) return } }).resume() } }
How to use the AsyncImageLoader class?
See below. As I used in collectionView: UICollectionView, cellForItemAt indexPath: IndexPath
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { AsyncImageLoader.sharedLoader.imageForUrl(urlString: list.poster_image_url) { (image, url) -> () in DispatchQueue.main.async { cell.imageView.image = image } } }