当服务器上的图片文件更改时,我的应用程序中使用SDWebImage缓存的图像会发生什么?

50
我正在使用SDWebImage库在我的应用程序中缓存网络图片: https://github.com/rs/SDWebImage/blob/master/README.md 当前用法:
[imageView setImageWithURL:[NSURL URLWithString:profilePictureUrl] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
我的问题是:图片被缓存后,如果服务器上的图片文件在几天后被更新了呢?
目前我的应用仍然显示已缓存的图片。
我在设置缓存超时或者识别文件大小变化的任何文档中都没有看到相关内容。
如果有人使用过这个库并能提供帮助,将不胜感激。
先行致谢。
10个回答

70
我查看了源代码。它处理setImageWithURL方法的方式如下:
  1. 询问内存缓存是否存在该图像,如果是,则返回该图像并停止进一步操作
  2. 询问磁盘缓存是否存在该图像,如果是,则返回该图像并停止进一步操作
  3. 尝试下载该图像,在成功时返回图像,否则保留占位符图像
在磁盘上有旧版本时,没有发送请求询问远程服务器是否有新版本,例如使用HTTP协议的ETags
深入挖掘,缓存时间在SDImageCache.m中设置为静态值。
static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week

它不能通过setter改变。

只要缓存中的图像有效,SDWebImage库就不会下载任何新内容。一周后,它将下载更改后的图像。


4
一周有多少秒:60秒60分钟24小时*7天=604800秒。一天是86400秒。 - Nick Weaver
4
这是否意味着一周后缓存中的所有资产都将被重新下载?即使它们仍然相同? - zanona
1
@zanona 没错。SDWebImage没有使用Etag来检测更改。 - Nick Weaver
在SDWebImage 5.0+中,maxCacheAge已更名为maxDiskAge。您可以像这样设置以秒为单位的最大缓存时间。有关更多详细信息,请参见以下链接: https://dev59.com/rIfca4cB1Zd3GeqPpetS#55536290 - Dipak

27
你可以使用options参数。 Swift 版本:
imageView.sd_setImage(with: URL(string: URLWithString:profilePictureUrl),
                      placeholderImage: UIImage(named: "placeholder"),
                      options: .refreshCached,
                      completed: nil)

Objective-C版本:

[imageView sd_setImageWithURL:[NSURL URLWithString:profilePictureUrl]
             placeholderImage:[UIImage imageNamed:@"placeholder.png"]
             options:SDWebImageRefreshCached
             completed: nil];

干杯!


13

SDImageCache的问题(现在有一个setter:maxCacheAge)在于SDWebImage从未真正主动使用它。您需要在某个时间点调用cleanDisk来清除缓存中的旧数据。注意:SDWebImage在应用程序终止时确实会调用cleanDisk,但应用程序不能保证从操作系统获得终止通知。


3
仅作警告,截至2014年9月,这个说法实际上是不正确的。 检查SDImageCache.m文件中的-(void)cleanDiskWithCompletionBlock函数。 - Luke
这个问题在tvOS 15平台上仍然存在,我需要手动调用SDImageCache.shared.deleteOldFiles()来删除过期的缓存。 - Mr.SwiftOak

8
    NSURL *imageUrl = nil;
    NSDate *lastUpdate = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastUpdate"];
    NSDate *currentDate = [NSDate date];

    if (lastUpdate == nil 
        || ![lastUpdate isKindOfClass:[NSDate class]] 
        || [currentDate timeIntervalSinceDate:lastUpdate] > 60 * 60 *24) {
            [[NSUserDefaults standardUserDefaults] setObject:currentDate forKey:@"lastUpdate"];
            NSString *urlString = [NSString stringWithFormat:@"http://yourdomain.com/image/image.png?%f", [currentDate timeIntervalSince1970]];
            imageUrl = [NSURL URLWithString:urlString];
    }

8
如果您想要更改Swift中默认缓存的持续时间,请在AppDelegate中进行设置。 版本3:
SDWebImageManager.sharedManager().imageCache.maxCacheAge = CACHE_TIME_IN_SECONDS

第4版:

SDWebImageManager.shared().imageCache?.config.maxCacheAge = CACHE_TIME_IN_SECONDS

我相信这只会影响在此值设置后缓存的图片。例如,如果您的应用程序使用默认缓存过期时间缓存了一张图片,然后将其更改为其他内容,则您的图片仍将在一周后才会过期。解决此问题的简单方法是清除您的缓存。

4

SDWebImage默认采用积极缓存技术。但现在他们提供了一种方法,可以尊重HTTP缓存控制头并获取最新的图像。

为此,他们有了一个新的方法,在选项中您可以传递SDWebImageRefreshCached。

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

您可以在此处找到完整的方法细节和解释。

4
以下是我的观察:
1. 如果图像名称/路径相同,SDWebImage 将不会在 1 周内重新下载它。 2. 不考虑图像名称,SDWebImage 将在下载后的 1 周内重新下载该图像。 static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week 3. 他们有一个数据库,其中存储了所有图像 URL。对于他们来说,图像 URL 就像主键(唯一键)一样。 因此,基本上他们所做的是,如果 URL 发生更改并且不存在于数据库中,则下载它。
从我的角度来看,他们所做的是正确的。例如,如果您上传图像给用户 A,那么图像名称必须更改,这是基本的。我知道一些开发人员喜欢图像名称保持相同(例如 userA.png)。

3

SDWebImage的流程:

1) SDWebImage 缓存从服务器获取的图像。

2) SDWebImage 使用url作为缓存中图像的键。

3) SDWebImage 检查:

如果它能够从缓存中获取图像 - OK

如果不行(例如url已更改)- 将无法从缓存中获取图像

因此,实际上,您将获得空的ImageView,并且SDWebImage 必须重新从服务器检索图像。


3

最新的Swift 3.0*和SDWebImage

SDWebImageManager.shared().imageCache?.deleteOldFiles(completionBlock: nil)

1

我在git上阅读SDWeb的自述文件时发现:

在您的情况下,您可以使用SDWebImageRefreshCached标志。这会略微降低性能,但会尊重HTTP缓存控制头:

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

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