문제

I am using the SDWebImage library to cache web images in my app:

https://github.com/rs/SDWebImage/blob/master/README.md

Current Usage:

[imageView setImageWithURL:[NSURL URLWithString:profilePictureUrl] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

My question is what happens once the image has been cached and then a couple of days later that image file on the server has been updated with a new image?

At the moment my application is still displaying the cached image.

I can't see in any of the documentation on setting a cache timeout or something that recognises that the file size has changed.

If anyone has experience using this particular library then any help would be greatly appreciated.

Thanks in advance.

도움이 되었습니까?

해결책

I had a look at the source code. It processes the setImageWithURL method like this:

  1. Ask the memory cache if the image is there, if yes return the image and don't go any further
  2. Ask the disk cache if the image is there, if yes return the image and don't go any further
  3. Try to download the image, return image on success else keep the placeholder image

There is no request sent to ask the remote server if there is a new version while there is something old on disk, like using ETags of the HTTP protocol.

Digging a bit deeper the cache time is set to a static value in SDImageCache.m

static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week

it cannot be changed with a setter.

So as long as the image in the cache is valid the SDWebImage lib won't download anything new. After a week it'll download your changed image.

다른 팁

You can use options parameter.

Swift version:

imageView.sd_setImage(with: URL(string: URLWithString:profilePictureUrl),
                      placeholderImage: UIImage(named: "placeholder"),
                      options: .refreshCached,
                      completed: nil)

Objective-C version:

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

Cheers!

The problem with SDImageCache's aging (which now has a setter: maxCacheAge) is that SDWebImage never really proactively does anything with it. You need to invoke cleanDisk yourself at some point to purge old data from the cache. Note: SDWebImage does invoke cleanDisk when the app terminates, but apps are not guaranteed to get a termination notification from the OS.

    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];
    }

Incase you are looking to change the default cache duration in Swift. Set this in your AppDelegate.

Version 3:

SDWebImageManager.sharedManager().imageCache.maxCacheAge = CACHE_TIME_IN_SECONDS

Version 4:

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

-

I believe this only effects images that are caches after this value is set. IE if your app cache an image with the default cache expiration and then change it something else, your images will still only expire after a week. An easily solution to this is to just clear your cache.

Below is what I have observed.

  1. If the image name/ path is same, SDWebImage will not download it again for 1 week.

  2. Irrespective of Image name, SDWebImage will re-download the image after 1 week (from the time it is downloaded).

    static NSInteger cacheMaxCacheAge = 60*60*24*7; // 1 week

  3. They have one Database where all images URL are stored. For them, image URL is like primary key (unique key).

So basically what they do is if the URL is changed and not present in DB, download it.

From my point of view what they are doing is RIGHT. Ex. If you upload image let's say for user A, the image name has to be changed & this is basic. I know some developer prefer image name to be same (like userA.png always).

SDWebImage does aggressive caching by default. But now they give the option to respect your HTTP caching control headers and get the latest image.

For this they have a new method where in options you can pass SDWebImageRefreshCached

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

You can find the complete method details and explanation here.

SDWebImage flow:

1) SDWebImage caches image retrieved from the server

2) SDWebImage uses url is a key to the get image from cache

3) SDWebImage checks:

if it is able to get the image from cache - OK

if no (e.g url was changed) - not able to get the image from cache

so actually, you will get empty ImageView(s) and SDWebImage must retrieve images from the server again

Latest Swift 3.0* and SDWebImage

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

As I read in the SDWeb readme in git, It might help:

In your case, you may use the SDWebImageRefreshCached flag. This will slightly degrade the performance but will respect the HTTP caching control headers:

[imageView sd_setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"]
                 placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
                          options:SDWebImageRefreshCached];
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top