Gik
Gik

Reputation: 537

Is there a way to refresh the cache used by UIImage class?

In my iOS app I am using the +imageNamed: method to load an image (many times and in many different places in the code). In one case the user might update (download) a new image. When I try to load the new, it will show the old, due to caching. From the "Is there a way to clear the cache used by UIImage class?" question, I saw that I have to use the -initWithContentsOfFile: method.

But this will not take advantage of the caching speedup that the +imageNamed: enjoys. All I want is to "tell" the cache that the file has changed, so it needs to "re-cache" it. And then keep using the +imageNamed: method with the new cached image.

In other words, I use the +imageNamed: method (say) 10 times, I change the image, I "tell" the cache, then I continue use the +imageNamed: method another (say) 10 times. If I change all the +imageNamed: to -initWithContentsOfFile: then I lose the caching advantage.

Is there a way/trick to do that?

Upvotes: 1

Views: 918

Answers (3)

Michel Goñi
Michel Goñi

Reputation: 117

Maybe I just got late to the party...but using

+ (UIImage *)imageWithContentsOfFile:(NSString *

I got rid of the cache issue.

Hope it helps!!

Upvotes: 0

Hamish
Hamish

Reputation: 80781

You'll probably just have to figure out your own way of caching your images.

I'd suggest using a UIImage category with a static NSMutableDictionary that can hold your cached images. Then just use your custom caching method when initialising your UIImage.

For example:

@interface UIImage (UIImageCache)

+(UIImage*) cachedImageFile:(NSString*)imageFile;
+(void) resetCacheForImageFile:(NSString*)imageFile;

@end

@implementation UIImage (UIImageCache)

static NSMutableDictionary* cachedImages;

+(UIImage*) cachedImageFile:(NSString*)imageFile {

    // Optional error checking
    NSAssert1([[NSFileManager defaultManager] fileExistsAtPath:imageFile], @"Warning! The image file %@ doesn't exist.", imageFile);

    if (!cachedImages) cachedImages = [NSMutableDictionary dictionary];

    UIImage* cachedImg = [cachedImages objectForKey:imageFile];
    if (cachedImg) return cachedImg; // Image is cached, return it

    else { // No cached image, create one
        UIImage* img = [UIImage imageWithContentsOfFile:imageFile]; // iOS won't auto-cache the image.
        [cachedImages setObject:img forKey:imageFile];
        return img;
    }

}


+(void) resetCacheForImageFile:(NSString*)imageFile {
    [cachedImages removeObjectForKey:imageFile];
}

@end

Upvotes: 1

James P
James P

Reputation: 4836

There is no API for clearing the cache. If your app is not destined for the app store you could call the private method:

[UIImage _flushSharedImageCache];

However I wouldn't want this anywhere near production code.

Instead I would create a category on UIImage and add a method for returning the desired image from a filename. This name would be stored and then updated when your new image is downloaded. You will get the benefit of caching, without any hacky workarounds.

Depending on the complexity of your project, a simple find and replace shouldn't take too long.

Although I'm now questioning how your app is working currently, imageNamed only looks for files in your app's bundle, so won't work for images downloaded by the user.

Upvotes: 1

Related Questions