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.
Kingfisher is a powerful, pure-Swift library for downloading and caching images from the web. It provides you a chance to use a pure-Swift way to work with remote images in your next app.
Cache is a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere.
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With