Reputation: 660
I need to cache images on disk but to limit them say to 20 images. I am trying Nuke
library. When I run
Nuke.loadImage(with: url, options: options, into: imageView)
image is cached as long as I am inside my View Controller. When I leave the views, next time images are being fetched again. So how do I make Nuke
(or other lib) save those images for specific image count or time.
Before trying Nuke
I was just saving images to Documents folder of the app every time I fetch image. I am sure there is a better way.
Update: I was able to do it with Kingfisher
.
func getFromCache(id: String) {
ImageCache.default.retrieveImage(forKey: id, options: nil) {
image, cacheType in
if let image = image {
self.galleryImageView.image = image
} else {
print("Not exist in cache.")
self.loadImage()
}
}
}
private func loadImage() {
ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) {
(image, error, url, data) in
if let image = image {
self.galleryImageView.image = image
ImageCache.default.store(image, forKey: id, toDisk: true)
}
}
}
If I understand correctly, first retrieveImage
fetches images from disk cache. Later from memory cache. And it frees them only when memory warning received. I hope it does. God help us.
Upvotes: 3
Views: 2383
Reputation: 58103
There are several advanced options for image caching. You can get a direct access to Memory Cache
(default Nuke's ImagePipeline
has two cache layers):
// Configure cache
ImageCache.shared.costLimit = 1024 * 1024 * 100 // Size in MB
ImageCache.shared.countLimit = 20 // You may use this option for your needs
ImageCache.shared.ttl = 90 // Invalidate image after 90 sec
// Read and write images
let request = ImageRequest(url: url)
ImageCache.shared[request] = image
let image = ImageCache.shared[request]
// Clear cache
ImageCache.shared.removeAll()
Also, use ImagePreheater
class. Preheating (a.k.a. prefetching) means loading images ahead of time in anticipation of their use. Nuke
lib provides an ImagePreheater
class that does just that:
let preheater = ImagePreheater(pipeline: ImagePipeline.shared)
let requests = urls.map {
var request = ImageRequest(url: $0)
request.priority = .low
return request
}
// User enters the screen:
preheater.startPreheating(for: requests)
// User leaves the screen:
preheater.stopPreheating(for: requests)
You can use Nuke
lib in combination with Preheat
library which automates preheating of content in UICollectionView
and UITableView
. On iOS 10.0 and above you might want to use new prefetching APIs provided by iOS instead.
Upvotes: 2