Long story short, I just updated to Xcode 6 to check how my app works on iOS 8. I noticed that it doesn\'t use the cache even though it should. I\'m using AFNetworking setting t
NSURLConnection is not working properly. It will store responses properly, but it never purges the cache (diskCapacity is ignored) on iOS 8.0 so the cache will grow without limit, though manually clearing the cache does work. This is fixed in iOS 8.1, although removeCachedResponseForRequest: still does not work.
Also, if you specify a cache size smaller than 5 megs, it will not cache anything.
Both NSURLCache
and NSURLSession
are buggy.
Even if you set NSURLRequestReturnCacheDataElseLoad
for request, iOS may try to reload file from server.
It happens for example when cached response has Vary
header.
Also please notice that method
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
use User-Agent
header from request to distinguish cached objects.
It means iOS will store the same file twice, if you access it by NSURLSession and UIWebView, because User-Agent
is different.
I'm almost certain that iOS 8.0 has broken NSURLSession
's ability to cache HTTP response data. I've opened a radar with Apple about this issue.
Here's some sample code I wrote to prove this:
NSURLSession *session = [NSURLSession sharedSession];
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
diskCapacity:32 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURL *URL = [NSURL URLWithString:@"http://i.imgur.com/b5pyONe.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:5];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error occurred");
} else {
NSLog(@"Fetched resource!");
}
dispatch_semaphore_signal(semaphore);
}];
[task resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
request = [NSURLRequest requestWithURL:URL
cachePolicy:NSURLRequestReturnCacheDataDontLoad
timeoutInterval:5];
task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Something bad happened: %@", error);
} else {
NSLog(@"Fetched resource!");
}
}];
[task resume];
Even creating your own NSURLSession
-- with an NSURLSessionConfiguration
that has an NSURLCache
that you create yourself -- won't fix this issue. For now, if you need cached responses badly, you have to use NSURLConnection
.