0

I am implementing image caching in ios. Following is my function.

struct DownloadImage {

static let cache = NSCache<NSString,UIImage>()

static func downloadImage(with url: URL,completion: @escaping (_ image: UIImage?) -> ()) {
    let dataTask = URLSession.shared.dataTask(with: url) { (data, responseURL, error) in
        var downloadedImage: UIImage?

        if let data = data {
            downloadedImage = UIImage(data: data)
        }
        if downloadedImage != nil {
            cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString)
        }
        DispatchQueue.main.async {
            completion(downloadedImage)
        }
    }
    dataTask.resume()
}


static func getImage(withURL url:URL,completion: @escaping (_ image: UIImage?) -> ()) {
    if let image = cache.object(forKey: url.absoluteString as NSString) {
        completion(image)
    } else {
        downloadImage(with: url, completion: completion)
    }
}  

}

The image is been cached but when I rebuild the project again, download image function is called even on the same URL?.

Can someone tell me what I am missing or why download image function is called?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Arinjay
  • 69
  • 2
  • 7
  • 1
    `NSCache` is an *in-memory* cache. The cache contents do not persist across application restarts. – Paulw11 Mar 11 '19 at 07:33
  • 1
    `NSCache` Object is storing image using, but you rebuild project or kill App and restart then `cache` is new initialize. But what you want in your code. – Pradip Patel Mar 11 '19 at 07:34
  • [SDWebImage](https://github.com/SDWebImage/SDWebImage) provides on-disk caching – Paulw11 Mar 11 '19 at 07:42
  • what I want is that if I again restart the app, I should be able to get the image from the cache in case of no internet. – Arinjay Mar 11 '19 at 07:54

2 Answers2

1

As everyone else has mentioned, what you need is persistent memory.

You can do to save them is:

let fileCoordinator = NSFileCoordinator()
fileCoordinator.coordinate(writingItemAt: someURL, options: .forReplacing, error: nil, byAccessor: { _ in
     do {
          try UIImagePNGRepresentation(image)?.write(to: someURL)
     } catch let error as NSError {
          print (error)
     }
})

And then to read it:

if let data = Data(contentsOf: someURL), let image = UIImage(data: data!) }
    return image
} else {
    print ("something wrong reading the image"
}
regina_fallangi
  • 2,080
  • 2
  • 18
  • 38
0

NSCache is just a fancy NSDictionary. It's not supposed to persist over sessions, and it's not guaranteed to keep objects in the memory even during the session.

So in your specific case, the cache is recreated each time you rebuild your app.

Adis
  • 4,512
  • 2
  • 33
  • 40