【问题标题】:What's the Kingfisher default cache behavior?Kingfisher 的默认缓存行为是什么?
【发布时间】:2017-08-20 07:35:17
【问题描述】:

我正在使用Kingfisher 库来缓存 UICollectionView 单元格中的图像。

我注意到调用kf_setImage(假设单元格名称为listCell,其ImageView 为imgMain)如下:

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

工作正常,它确实会缓存图像并在单元格重新出列时显示它(上下滚动时,我可以直接看到图像而无需重新下载它),但是当我拉刷新集合视图(调用具有相同确切参数的 API,这意味着它将返回相同的图像 url)图像已重新下载!我假设图像已经被缓存了。

为了更清楚,this link 包含描述我所面临的情况的 gif 图像。

那么,为什么图像会再次下载?这是翠鸟中缓存的默认行为吗?是否有任何配置需要编辑以符合我的预期?

我阅读了library documentation,但 - 不幸的是 - 我找不到与我所要求的内容相关的有用信息。

【问题讨论】:

    标签: ios swift caching kingfisher


    【解决方案1】:

    Kingfisher 默认使用整个 url 作为缓存键,因此您必须确保每次请求 API 时都有相同的图像 url 字符串。如果 URL 中附加了时间戳或版本号之类的内容,则缓存将失败。 (例如,http://example.com/image.png?time=123http://example.com/image.png?time=456 将被识别为两个不同的缓存键,尽管您可以从中获得相同的图像)。

    这是我能为您的手术绘制的唯一案例。如果这对你来说是真的,你可以创建一个ImageResource 来明确指定缓存键(它应该与你的原始 url 相关,但去掉附加的东西):

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

    【讨论】:

    • 感谢您的考虑。这正是我所面临的,下次调用API时URL参数不同。正如您在代码 sn-p 中提到的,使用 ImageResource 解决了我的问题。
    • 只是为了确保我做对了,ImageResource 的作用是:如果键是 not nil 它应该会识别现有图像,即使 url改了是吧?
    • 是的,你是对的。默认情况下,键将是您的 url 的绝对字符串。一旦你自己设置了,输入键就会被尊重并用于在缓存中搜索。
    【解决方案2】:

    根据我之前看到的 Kingfisher 加载单元格的行为,最初是获取图像并保存到缓存中。

    每次滚动时都会处理图像的更改、重新加载、从缓存中获取等。在您的 Pull to refresh 中,您正在重新加载数据源,因此 Kingfisher 会尝试再次重新加载缓存,当然,您可以避免它使用 Kingfisher 自己手动处理缓存或在 kf_setImage 方法的选项中指定。

    如果看到方法kf_setImage的签名:

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

    默认有options参数nil。您可以在这些参数中指定onlyFromCache,如果设置,Kingfisher 将仅尝试从缓存中检索图像,而不是从网络中检索。

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

    另一种方法是根据您的要求自定义 ImageCacheImageDownloader

    但是您需要小心,因为当您执行 Pull to Refresh 时,默认行为应该首先显示缓存中的图像并在它来自网络时对其进行更新,因此您需要以某种方式处理它.

    希望对你有帮助

    【讨论】:

    • 感谢您的回答。对于第一个应用程序启动,如果options 设置为onlyFromCache 它不会获取任何数据,我假设因为还没有缓存数据。
    • @AhmadF 当然可以!!! ,请记住,使用 Kingfisher,您可以指定缓存的持续时间、大小等。所以我的观点是您可以保存图像并在您想要的时间段内保留它
    • 所以,没有选项:第一次下载(缓存)图像(如果不存在)并在下次使用它(如果存在)......手动执行这样的功能对我来说有点困惑,不是因为我不那么聪明,而是我认为它应该存在:)
    • 要处理,恐怕你应该自己使用ImageCache
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 2010-11-04
    • 2020-10-27
    相关资源
    最近更新 更多