IOS 8 разорвал NSURLCache?

Короче говоря, я просто обновился до Xcode 6, чтобы проверить, как мое приложение работает на iOS 8. Я заметил, что он не использует кеш, хотя он и должен. Я использую AFNetworking для настройки cachePolicy следующим образом:

sessionManager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

У меня все еще есть устройство iOS 7, в котором я тестировал один и тот же код, и он работает там, как ожидалось.

У кого-нибудь есть решение для этого, или нам нужно ждать, пока Apple его исправит?

Ответы

Ответ 1

Я почти уверен, что iOS 8.0 сломал NSURLSession способность кэшировать данные ответа HTTP. Я открыл радар с Apple об этой проблеме.

Вот пример кода, который я написал, чтобы доказать это:

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];

Даже создание собственного NSURLSession - с NSURLSessionConfiguration с NSURLCache, которое вы создаете самостоятельно, не решит эту проблему. На данный момент, если вам нужны кэшированные ответы, вы должны использовать NSURLConnection.

Ответ 2

NSURLConnection работает неправильно. Он будет правильно хранить ответы, но никогда не очищает кеш (diskCapacity игнорируется) на iOS 8.0, поэтому кеш будет расти без ограничение, хотя ручная очистка кеша работает. Это исправлено в iOS 8.1, хотя removeCachedResponseForRequest: по-прежнему не работает.

Кроме того, если вы укажете размер кеша меньше 5 мегабайт, он ничего не будет кэшировать.

Ответ 3

Оба NSURLCache и NSURLSession ошибочны. Даже если вы установите NSURLRequestReturnCacheDataElseLoad для запроса, iOS может попытаться перезагрузить файл с сервера. Это происходит, например, когда кешированный ответ имеет заголовок Vary. Также обратите внимание, что метод

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request

используйте заголовок User-Agent из запроса, чтобы отличать кешированные объекты. Это означает, что iOS будет хранить тот же файл дважды, если вы обращаетесь к нему через NSURLSession и UIWebView, потому что User-Agent отличается.