arnaud del.
arnaud del.

Reputation: 912

Image caching for images in the Documents directory

My application download a package with images over HTTP. They are stored in the Documents/ directory, and displayed.

I read that the UIImage didn't work for caching image in the ".../Documents/" directory of the iphone/ipad (because only [UIImage imageNamed:] make use of cache, and it works only for images in the bundle). In addition, I want to be able to clear the cache when I download a new package.

So, here is what I wrote :

In Image.h

#import <Foundation/Foundation.h>

@interface Image : NSObject

+(void) clearCache;

+(UIImage *) imageInDocuments:(NSString *)imageName ;

+(void)addToDictionary:(NSString *)imageName image:(UIImage *)image;

@end

In Image.m

#import "Image.h"

@implementation Image

static NSDictionary * cache;
static NSDictionary * fifo;
static NSNumber * indexFifo;
static NSInteger maxFifo = 25;

+(void)initialize {
    [self clearCache];
}

+(void) clearCache {
    cache = [[NSDictionary alloc] init];
    fifo = [[NSDictionary alloc] init];
    indexFifo = [NSNumber numberWithInt:0];
}

+(UIImage *) imageInDocuments:(NSString *)imageName {
    UIImage * imageFromCache = [cache objectForKey:imageName];
    if(imageFromCache != nil) return imageFromCache;

    NSString * path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString     stringWithFormat:@"/Documents/%@", imageName, nil]];
    UIImage * result = [UIImage imageWithContentsOfFile:path];
    [self addToDictionary:imageName image:result];
    return result;
}

+(void)addToDictionary:(NSString *)imageName image:(UIImage *)image {

    NSMutableDictionary *mFifo = [fifo mutableCopy];
    NSString * imageToRemoveFromCache = [mFifo objectForKey:indexFifo];
    [mFifo setObject:imageName forKey:indexFifo];
    fifo = [NSDictionary dictionaryWithDictionary:mFifo];
    // indexFifo is like a cursor which loop in the range [0..maxFifo];
    indexFifo = [NSNumber numberWithInt:([indexFifo intValue] + 1) % maxFifo];

    NSMutableDictionary * mcache = [cache mutableCopy];
    [mcache setObject:image forKey:imageName];
    if(imageToRemoveFromCache != nil) [mcache removeObjectForKey:imageToRemoveFromCache];
    cache = [NSDictionary dictionaryWithDictionary:mcache];
}

@end

I wrote it to improve performance on loading image. But I'm not sure with the implementation. I wouldn't like to have the opposite effect :

What do you think ? is it awkward ?

ps : I put the code on gist.github : https://gist.github.com/1719871

Upvotes: 0

Views: 1458

Answers (1)

Conrad Shultz
Conrad Shultz

Reputation: 8808

Whoa... are you implementing your own object cache? Have you first taken a look at NSCache to see whether it suits your needs?

(I don't believe UIImage conforms to NSDiscardableContent, so you would have to either purge the cache yourself or wrap UIImage if you want the cache to handle low-memory conditions. But as you note in your question, your current implementation doesn't do that either.)

Upvotes: 3

Related Questions