RealNmae
RealNmae

Reputation: 660

Image Caching – How to control when images are disposed?

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

Answers (1)

Andy Jazz
Andy Jazz

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

Related Questions