Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does disk caching with NSURLRequest and NSURLConnection actually work on the iPhone?

I have a UITableView whose cells contain custom ImageViews that asynchronously load the images from the internet. To load those images I use NSURLRequest and NSURLConnection which works fine. The only problem is that the images are not cached and therefore are downloaded every time they are used. I tried to set the cachePolicy of the NSURLRequest to "NSURLRequestReturnCacheDataElseLoad" with no effect.

It seems from the last answer on link that disk caching is not supported with NSURLRequest on the iPhone. Is this correct?

If it should actually work, I'd be interested to know what could be the reason that it doesn't work in my case.

Here's the code:

NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://myurl"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0];


connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
like image 240
kiteloop Avatar asked Oct 15 '22 09:10

kiteloop


2 Answers

I think it should work. If it does not then it could mean that the web server is actually serving content that is not cacheable. For example because it is not setting the right headers.

If you can post a link to one of the images then we can take a close look.

HTTP/1.1 200 OK
Date: Mon, 01 Mar 2010 12:40:46 GMT
Server: Apache
Last-Modified: Mon, 01 Mar 2010 09:33:29 GMT
ETag: "25e8dd2-11a6-480b9f1178c40"
Accept-Ranges: bytes
Content-Length: 4518
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: image/png

This is what one of your images returns as headers. I don't see a Expires or Cache-Control header, so that may be why they are not cached. I think as far as WebKit is concerned, this is dynamic content that should be reloaded every time.

like image 173
Stefan Arentz Avatar answered Oct 16 '22 23:10

Stefan Arentz


NSURLCache on-disk caching has worked since iOS 5. By default NSURLCache does not use on-disk caching, you must enable it yourself:

NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:(1024*1024*512) diskCapacity:(1024*1024*1024 * 100) diskPath@"Cache.db"];
[NSURLCache setSharedURLCache:cache];

This will set the global URL cache to be used for the URL loading system. For the most part, this will "just work". If your request uses NSURLRequestUseProtocolCachePolicy, which is the default, the URL loading system will cache with the lifetimes indicated by the remote server response. Services such as REDbot can tell you what the cache lifetime of a given response would be.

NSURLSessionConfiguration can be configured to use separate caches, however in practice this does not work as documented. As of iOS 8, if multiple NSURLCaches are configured only the first will actually be used.

There are additional undocumented behaviors when using on disk storage with NSURLCache: - If the diskCapacity is set to less than 5MB, it will not be used. - Purging and resizing the cache often does not work as expected. Some of this was fixed in iOS 8, some was not. - currentDiskUsage information is often incorrect. - On some iOS releases NSURLCache ignores the limit set by diskCapacity and grows the on-disk cache without limits.

That said, NSURLCache on disk caching does generally do the right thing. If you create an on-disk cache as above when your application starts up the cache will persist responses to the disk and the URL loading system will use those cached responses. Once you have set the cache as above, you do not need to interact with the cache directly - the URL loading system does that for you. The exception is NSURLSession, where caching still seems to be a bit broken.

like image 37
quellish Avatar answered Oct 17 '22 00:10

quellish