I'm trying to figure out how to use the URL loading framework to load URLs taking advantage of caching.
I am using NSURLConnections and feeding them NSURLRequests. I have even set the cachePolicy on those requests to NSURLRequestReturnCacheDataElseLoad. The first time I load a request, it does automatically get put in the cache ([NSURLCache sharedCache]
has it). But the next time I load the same request, the NSURLConnection seems to ignore what's in the cache and reload the data.
Am I supposed to be manually implementing cache lookups and returning cached data? Does NSURLConnection not do this? Or is there some way to get the framework to use the cache seamlessly?
UPDATE: Tried the following without success:
- Setting the request cache policy to
NSURLRequestReturnCacheDataElseLoad
instead of NSURLRequestUseProtocolCachePolicy
- Re-using the request object instead of making a new one
- Using
+[NSURLConnection sendSynchronousRequest:returningResponse:error:]
instead of loading asynchronously
NOTE iOS 5 onwards provide a sharedURLCache that has both memory and disk capacity.
Nothing will cache unless you set the NSURLCache to have some capacity:
// A 10MB cache. This a good avatar-image-cache size but might be too
// large for your app's memory requirements. YMMV.
[[NSURLCache sharedURLCache] setMemoryCapacity:1024*1024*10];
The default iPhone NSURLCache instance refuses to ever cache to disk. if you need this behaviour you must sub-class NSURLCache and implement your own disk cache. I have found numerous examples of disk caches on GitHub, though none of them do the entirely necessary "prune" step satisfactorily IMHO.
It will indeed use NSURLCache automatically, at least in some circumstances. Certainly it does in the following code:
EDIT - works in a OS X 10.6 Cocoa app, not iPhone (misread question)
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
// run request with default cache policy
NSMutableURLRequest *req=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://en.wikipedia.org/"]];
NSData *data=[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil];
NSLog(@"Received %d bytes", [data length]);
sleep(10);
// now run it asking it to use the cache
[req setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
data=[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil];
NSLog(@"Received %d bytes", [data length]);
return 0;
}
Have you tried messing with the connection:willCacheResponse:
method? According to the URL Loading System documentation, "By default the data for a connection is cached according to the support provided by the NSURLProtocol subclass that handles the request. An NSURLConnection Delegationdelegate can further refine that behavior by implementing connection:willCacheResponse:."