如何使用SDWebImage在服务器上的图片被更改后更新缓存中的图片

23

我正在使用SDWebImage库从服务器下载图片。

https://github.com/rs/SDWebImage

当服务器上的图片使用相同的URL进行更新时,SDWebImage无法更新缓存中的图片。

6个回答

20

SDWebImage 默认会进行一些缓存,因此如果图像发生更改,最好使用新的URL。例如,如果您可以控制URL并且可以在每次更改图像时更改它,则可以这样做。

如果不是这种情况,请尝试在 options 字段中使用 SDWebImageRefreshCached 以遵守 HTTP 缓存控制标头,像这样:

[imageView setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"]
          placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
                   options:SDWebImageRefreshCached];

点击这里查看更多信息。


6
我已经尝试了这个代码,但是它没有更新图片。问题在于,当我在服务器上更新图片并返回到之前的屏幕时,在重新加载表格视图后仍然显示相同的图片。 - Shubham
你必须确保服务器设置了正确的HTTP缓存控制头。我刚刚测试了一个带有主->详细结构和单元格的示例项目,其中包含来自dropbox共享的URL的图像,在详细屏幕上更改了dropbox上的图像,同时保持相同的名称和共享URL,确保dropbox完成同步,然后在应用程序上按返回键,图像就会更新。请查看示例项目RefreshCachedImageTest - Edgar
是的,它对于Dropbox图像完美地工作。我认为问题来自服务器端。你有关于服务器端的任何想法吗? - Shubham
之前的方法虽然可用,但已被弃用,现在可用的方法是这个... [photoView setImageWithURL:[NSURL URLWithString:strPhoto] placeholderImage:[UIImage imageNamed:@"imageName"] options:SDWebImageRefreshCached usingActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - Aanchal Chaurasia
1
这仍然无法正常工作,当服务器URL更改时图像也随之更改...但URL与以前相同,库无法检测到图像的更改。 - Pulkit Kumar Singh

13

更新:我已经写了一份完整的缓存指南,包括缓存验证,具体请见https://kean.github.io/blog/image-caching

SDWebImage在设置SDWebImageRefreshCached选项时使用NSURLCache。苹果的URL加载系统实现了HTTP缓存,包括缓存响应的验证。 HTTP缓存相当复杂,但有许多初学者指南可供参考:

基本上,服务器需要在每个响应中包含一些HTTP缓存控制头。有许多不同的策略可以用于实现重新验证。您可以使用Last-ModifiedETag。这样,每次客户端发送请求时,它都会自动将先前缓存响应中的Last-ModifiedETag值包括在请求中。如果该图像未更改,则服务器将响应状态码302(未修改),NSURLConnection/NSURLSession将透明地从NSURLCache中提供缓存响应。您不必再次下载数据,但仍需每次发出请求时与服务器进行检查。

您还可以使用HTTP缓存控制指定到期日期。如果使用了到期机制,NSURLConnection/NSURLSession将在缓存响应未过期之前不会重新验证缓存响应。

有关HTTP缓存控制的更多信息,请参见上面的链接。 HTTP缓存是一种通用的缓存机制,应尽可能使用它。

我建议使用Nuke框架进行图像加载(免责声明:由我编写)。它默认使用NSURLCache,同时还具有保存解压图像的内存缓存。


另外,由于我正在尝试使用Nuke,有没有一种方法可以仅从缓存中删除特定的图像并重新加载新的图像?还有一种清除整个缓存的方法,以便所有图像都从服务器重新加载? - vishal dharankar

6

这是一个使用 Swift 3 编写的代码,用于每次刷新缓存

imgCardBack.sd_setImage(with: URL(string: objUserData.back_image!), placeholderImage:UIImage(named: "cardBack"), options: .refreshCached)

你使用了最新版本的SDWebImage吗? - Hardik Thakkar
你使用这个方法的目的是什么?因为大多数情况下,当我们更新任何图片且其URL相同时,但此时图片已经更新,我们可以使用上述方法来获取新的更新图片。 - Hardik Thakkar
是的,为了达到同样的目的,我已经尝试过了。但仍然无法正常工作,它仍然显示旧图像。 - The iCoder
图片URL是由后端开发人员创建的吗?还是您可以为其指定任何名称? - Hardik Thakkar
让我们在聊天中继续这个讨论 - Hardik Thakkar
所以你可以用其他方法解决这个问题,你可以告诉他/她在图像URL中添加时间戳值,这样每次URL都不同,就不需要使用缓存函数,它会自动更新。 - Hardik Thakkar

3

Swift 4 只需在SDWebImage库中使用以下函数:

SDImageCache.shared().removeImage(forKey: (ImagePath), withCompletion: nil)

这个函数将删除内存和磁盘中保存的现金,然后只需在相同的位置上传您的新图像,它就能完美地工作。


请注意,ImagePath是您用于下载图像的路径,不含URL头。 - Remon Atef
如何从 URL 中获取路径? - Lee Probert
它可以工作。图像路径基本上是图像的URL,而该URL被用作NSCache的键。 - Abhinav Dobhal

1

请前往文件SDWebImageManager.m的第176行更改此行

if (options & SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache;

转化为中文:"

到下面的代码。

"
if (options & SDWebImageRefreshCached) {
      // force progressive off if image already cached but forced refreshing
      downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
      // remove SDWebImageDownloaderUseNSURLCache flag
      downloaderOptions &= ~SDWebImageDownloaderUseNSURLCache;
      //ignore image read from NSURLCache if image is cached but force refreshing
       downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
}

对我而言,它的效果非常好。

-3
如果URL没有改变,SDWebImage就无法知道服务器上的图像是否已更改。

感谢您的回复。当服务器上的图像更新时,URL保持不变。问题在于,当我在服务器上更新图像并返回到先前的屏幕时,重新加载表视图后,图像仍然保持不变。 - Shubham
是的,图像是相同的,因为已经缓存了,并且URL没有更改。因此,SDWebImage无法知道服务器端的图像已更改。请尝试Edgar的解决方案。 - salabaha
是的,这就是问题所在。但是当我重新加载表格视图时,它应该更新图像。 - Shubham
当您重新加载TableView时,缓存的图像会显示出来,因为SDWebImage在内部缓存了您的图像。我的意思是,每次您重新加载TableView时,SDWebImage都会检查它是否缓存了特定URL的图像,如果有,则显示它。因此,只要URL未更改,图像也不会更改。 - salabaha
如果您无法访问服务器并且在更改图像时无法更改URL,目前我看到的唯一解决方案是在重新加载表格视图之前清除SDWebImage缓存。 - salabaha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接