0

I initialized NSURLCache in my app delegate like so:

int cacheSizeMemory = 4*1024*1024;  // 4MB
int cacheSizeDisk   = 32*1024*1024; // 32MB
MyServerCache *sharedCache = [[MyServerCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
[MyServerCache setSharedURLCache:sharedCache]; 

Then I create a request with default cache policy and call:

[NSURLConnection sendSynchronousRequest: urlRequest
                      returningResponse: &response
                                  error: pError ];

The response is of type "application/json" and has "Cache-Control" set to "private, max-age=600". The response is only 874 bytes (shouldn't be too large to cache), however NSURLCache does not seem to work.

I have run this on a simulator and looked for the on-disk cache which doesn't seem to exist, so I subclassed NSURLCache (MyServerCache) and overrode the following methods to see if they were being called:

-(NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
  NSLog(@"Returning cached response for request:  %@", request);
  return [super cachedResponseForRequest:request];
}

-(void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request
{
  NSLog(@"Caching response for request: %@", request);
  [super storeCachedResponse:cachedResponse forRequest:request];
}

No matter what I do (and I've tried several different API's and responses), NSURLCache never seems to cache anything. I can never find the on-disk cache in the file system, and the methods above are never called on my subclass of NSURLCache (MyServerCache).

I'd really like to use this rather than rolling my own cache, but I have no idea why it's not working or how to get it to work. Please help.

HackyStack
  • 4,887
  • 3
  • 22
  • 28
  • What is UVMServerCache? Why don't you use NSURLCache instead of this class? – Ievgenii Jan 27 '14 at 17:40
  • 1
    It is a subclass of NSURLCache, where I have only overridden the methods mentioned above. I did this to be able to know if it's actually trying to cache responses and/or return cached responses. Because I'm using a class method on NSURLConnection, I can't implement it's delegate methods to try to intercept there... so subclassing NSURLCache seemed like the only other option... – HackyStack Jan 27 '14 at 17:50
  • Did you try to use standard class instead of your custom? Only for test purposes, maybe you will find some disk cache after this? – Ievgenii Jan 28 '14 at 07:13
  • I tried that first. When that didn't work, I subclassed to get better visibility into what was actually happening. – HackyStack Jan 28 '14 at 12:15
  • @HackyStack Did you ever git this figured out? I'm working on something similar using iOS7's NSURLSession classes (which make use of NSURLCache). http://stackoverflow.com/questions/21957378/how-to-cache-using-nsurlsession-and-nsurlcache-not-working – John Erck Feb 24 '14 at 20:31

1 Answers1

0

You have to create your request with the NSURLRequestUseProtocolCachePolicy and it works perfectly out-of-the box with NSURLCache.

NSURLRequestCachePolicy cachePolicy = NSURLRequestUseProtocolCachePolicy;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                       cachePolicy:cachePolicy 

You can read about the NSURLRequestCachePolicy here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/#//apple_ref/c/tdef/NSURLRequestCachePolicy

A little bit confusing ist that iOS always returns a 200 - Success so you will never get a 304 - Resource not Modified when a response is coming from cache. So it´s more easy to see the cache policy working when monitoring the server side.

You can use https://github.com/PaulEhrhardt/Simple-Cache-Test to validate cache-control, expires and ETag with a little local ruby server. It´s just a few lines to set-up. I tested both successfully with 7.1 and 8.4 iOS SDK.

ehrpaulhardt
  • 1,607
  • 12
  • 19