Did iOS 8 break NSURLCache?

2020-05-18 03:40发布

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 the cachePolicy like this:

sessionManager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

I still have an iOS 7 device in which I tested the same code and it works there as expected.

Does anyone have a solution for this, or do we need to wait for Apple to fix it?

3条回答
混吃等死
2楼-- · 2020-05-18 04:13

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.

查看更多
看我几分像从前
3楼-- · 2020-05-18 04:18

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.

查看更多
爷、活的狠高调
4楼-- · 2020-05-18 04:31

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.

查看更多
登录 后发表回答