How to cache images using URLSession in Swift

后端 未结 3 1523
鱼传尺愫
鱼传尺愫 2020-12-11 04:04

I would like to enhance the code below to cache images and only download them if they haven\'t been cached previously. I can\'t seem to find any good examples of how to use

3条回答
  •  时光取名叫无心
    2020-12-11 04:56

    Updated for Swift 4

    import UIKit
    
    let imageCache = NSCache()
    
    class ImageLoader: UIImageView {
    
        var imageURL: URL?
    
        let activityIndicator = UIActivityIndicatorView()
    
        func loadImageWithUrl(_ url: URL) {
    
            // setup activityIndicator...
            activityIndicator.color = .darkGray
    
            addSubview(activityIndicator)
            activityIndicator.translatesAutoresizingMaskIntoConstraints = false
            activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
            activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
    
            imageURL = url
    
            image = nil
            activityIndicator.startAnimating()
    
            // retrieves image if already available in cache
            if let imageFromCache = imageCache.object(forKey: url as AnyObject) as? UIImage {
    
                self.image = imageFromCache
                activityIndicator.stopAnimating()
                return
            }
    
            // image does not available in cache.. so retrieving it from url...
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
    
                if error != nil {
                    print(error as Any)
                    DispatchQueue.main.async(execute: {
                        self.activityIndicator.stopAnimating()
                    })
                    return
                }
    
                DispatchQueue.main.async(execute: {
    
                    if let unwrappedData = data, let imageToCache = UIImage(data: unwrappedData) {
    
                        if self.imageURL == url {
                            self.image = imageToCache
                        }
    
                        imageCache.setObject(imageToCache, forKey: url as AnyObject)
                    }
                    self.activityIndicator.stopAnimating()
                })
            }).resume()
        }
    }
    

    Usage:

    // assign ImageLoader class to your imageView class
    let yourImageView: ImageLoader = {
    
        let iv = ImageLoader()
        iv.frame = CGRect(x: 10, y: 100, width: 300, height: 300)
        iv.backgroundColor = UIColor(red: 0.94, green: 0.94, blue: 0.96, alpha: 1.0)
        iv.contentMode = .scaleAspectFill
        iv.clipsToBounds = true
        return iv
    }()
    
    
    // unwrapped url safely...
       if let strUrl = "https://picsum.photos/300/300".addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
          let imgUrl = URL(string: strUrl) {
    
          yourImageView.loadImageWithUrl(imgUrl) // call this line for getting image to yourImageView
    }
    

提交回复
热议问题