Search code examples
iosamazon-s3afnetworkingafnetworking-2cache-control

How to enable disk cache in AFNetworking on iOS


in my iOS app I'm the UIImageView category provided by AFNetworking in order to download images stored on Amazon S3. I thought that the default cache stored cached images on disk by default, however, for a number of reasons (missing HTTP headers, etc.) I realized I was mistaken. Images don't seem to be cached, they are downloaded at every execution.

Therefore I'm now trying a custom cache, as suggested here http://blog.originate.com/blog/2014/02/20/afimagecache-vs-nsurlcache/

Here's what I've done so far (which seems to work):

1) defined a custom NSURLCache called PlayerImageCache and initialized it in my app delegate in order to use 5MB of memory and up to 100MB of disk space

PlayerImageCache *sharedCache = [[PlayerImageCache alloc] initWithMemoryCapacity:5*1024*1024 diskCapacity:100*1024*1024 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];

2) overrided the storeCachedResponse method in order to always cache my images

- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse
                 forRequest:(NSURLRequest *)request
{
    if ([request.URL.absoluteString hasPrefix:playersImagesPrefix])
    {
        NSCachedURLResponse *modifiedCachedResponse = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:cachedResponse.data userInfo:cachedResponse.userInfo storagePolicy:NSURLCacheStorageAllowed];
        [super storeCachedResponse:modifiedCachedResponse forRequest:request];
    }
    else
    {
        [super storeCachedResponse:cachedResponse forRequest:request];
    }
}

3) forced every request to check the cache before downloading the image by using the NSURLRequestReturnCacheDataElseLoad policy

NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL urlForPlayer:self.playerId] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60];
[self.playerImage setImageWithURLRequest:imageRequest placeholderImage:[UIImage imageNamed:@"playerprofile"] success:nil failure:nil];

Will this be enough? Do I need to further customize my cache? Will this work even without the Cache-Control HTTP header?


Solution

  • The answer is yes! It works like a charm. I managed to greatly decrease the number of requests thanks to this trick.