Search code examples
iosobjective-cnsurlnsdocumentdirectory

iOS - Caching remote image


I am trying to cache images from the web to prevent excessive web requests to save battery and data. The basic idea is:

  1. Generate the string of the File's Location
  2. If the file exists then load it from the file
  3. If its not in existence (todo: or if the file is older than a day) then download the image from the web. Save it and load it.

However my code isn't working and I can't figure out why?

// imagesFileName has been correctly generated as as imageURL
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                     NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagesLibraryPath = [documentsDirectory stringByAppendingPathComponent:@"Images"];
NSString *imagePath = [imagesLibraryPath stringByAppendingPathComponent:imageFileName];


// Do We Have the icon in cache?
if (![[NSFileManager defaultManager] fileExistsAtPath:iconPath]) {
    // File Doesn't Exist - Load Image From URL
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imagesURL]];

    // Save Image
    [imageData writeToFile:imagePath atomically:YES];


    NSLog(@"Downloading & Importing Image");
    return [UIImage imageWithData:imageData];
} else {
    // Load the Image From The File But Update If Needed
    NSLog(@"Loading Image From Cache");
    return [UIImage imageWithContentsOfFile:imagePath];
}

Solution

  • There are a few problems here, but firstly, you have not said in what way your code isn’t working. Perhaps we can help more if you provide more information.

    I would not recommend using NSData’s dataWithContentsOfURL:. This method loads data synchronously (code execution in the current function stops until it finishes). This method should typically only be used for local files (with the file:// URL scheme), not for remote URLs. Look into loading the data asynchronously with NSURLSession or NSURLConnection, and read Apple’s URL Loading System Programming Guide.

    The URL loading system has built-in support for caching, so you should use that if possible and abandon this code entirely. Read Understanding Cache Access in the URL Loading System Programming Guide and also the NSURLCache article on HSHipster.

    If you do want to write your own caching system (which I do not recommended) then at least:

    • Use the Caches directory instead of the Documents directory (see ev0lution’s comment).
    • Avoid NSFileManager’s fileExistsAtPath: (see the note in the documentation). Instead try loading the image from disk and see if that fails (returns nil).