Ahmad F
Ahmad F

Reputation: 31645

What's the Kingfisher default cache behavior?

I am using Kingfisher library for the purpose of caching images in UICollectionView cells.

I noticed that calling kf_setImage (assuming that the name of the cell called listCell and its ImageView called imgMain) as follows:

listCell.imgMain.kf.setImage(with: URL(string: "MY IMAGE URL"),
                             placeholder: UIImage(named: "PLACEHOLDER IMAGE"))

works fine, it does caches the image and display it when cell has been re-dequeued (when scrolling up and down, I can see the image directly without re-downloading it), but when I pull to refresh the collection view (recall the API with the same exact parameters, which means that it will return the same image urls) the images have been re-downloaded! I assume that the images already have been cached.

To make it more clear, this link contains gif image that describes what am I facing.

So, why the images get downloaded once again? is it the default behavior of the caching in Kingfisher? Is there any configuration that should edited to behave as I expect?

I read the library documentation, but -unfortunately- I couldn't find and useful information related to what am I asking for.

Upvotes: 7

Views: 11670

Answers (2)

onevcat
onevcat

Reputation: 4631

Kingfisher is using the whole url as the cache key by default, so you have to ensure that you have the very SAME url string for the images every time you request your API. If there is something like timestamp or version number appended to the urls, the cache will fail. (eg. http://example.com/image.png?time=123 and http://example.com/image.png?time=456 will be recognized as two different cache keys, although you could get the same image from it).

This is the only case I could draw for your operation. If this is true for you, you could create an ImageResource to specify the cache key explicitly (which should be related to your original url, but get rid of the appended things):

let r = ImageResource(downloadURL: yourUrl, cacheKey: key)
imageView.kf.setImage(with: r, placeholder: yourImage)

Upvotes: 15

Victor Sigler
Victor Sigler

Reputation: 23451

According to the behaviour of Kingfisher I saw before for the loading of the cells initially is getting the images and saving to a cache.

Every time you scroll it handle it the change of image, reload, getting from the cache, etc. In your Pull to refresh you're reloading your data source, so Kingfisher would try to reload the cache again, of course, you can avoid it handling the cache manually yourself with Kingfisher or specifying in the options of the kf_setImage method.

If see the signature of the method kf_setImage:

public func kf_setImage(with resource: Resource?,
                          placeholder: Image? = nil,
                              options: KingfisherOptionsInfo? = nil,
                        progressBlock: DownloadProgressBlock? = nil,
                    completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

It has the options parameter nil by default. You can specify in these parameters like the onlyFromCache and if set, Kingfisher will only try to retrieve the image from the cache, not from the network.

imageView.kf.setImage(with: url, options: [.onlyFromCache])

The another way if customising the ImageCache and ImageDownloader to your requirements.

But you need to be careful because when you do a Pull to Refresh the default behaviour should be shown first the images from the cache and update it as it comes from the network, so you need to handle it in some way like this.

I hope this help you

Upvotes: 1

Related Questions