iOS 8 是不是破坏了 NSURLCache?

Posted

技术标签:

【中文标题】iOS 8 是不是破坏了 NSURLCache?【英文标题】:Did iOS 8 break NSURLCache?iOS 8 是否破坏了 NSURLCache? 【发布时间】:2014-09-21 23:39:05 【问题描述】:

长话短说,我刚刚更新到 Xcode 6 以检查我的应用在 ios 8 上的运行情况。我注意到它不使用缓存,即使它应该使用。我正在使用 AFNetworking 设置 cachePolicy,如下所示:

sessionManager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

我仍然有一个 iOS 7 设备,我在其中测试了相同的代码,它可以正常工作。

是否有人对此有解决方案,还是我们需要等待 Apple 解决?

【问题讨论】:

我注意到与 NSURLSession 非常相似的东西。我认为 NSURLConnection 仍然可以正常使用 NSURLCache。 我刚刚注意到与我的自定义 NSURLCache 子类相同(使用 AFNetworking2)(storeCachedResponse:forRequest: 被调用,但 cachedResponseForRequest: 从未被调用)。 【参考方案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(使用您自己创建的NSURLSessionConfigurationNSURLCache)也无法解决此问题。目前,如果您非常需要缓存响应,则必须使用NSURLConnection

【讨论】:

我就是这么想的。我很惊讶苹果最近遇到了多少问题。 Richard,你有苹果关于 NSURLCache 的答案吗?我真的需要在我的应用程序中缓存,但它在 iOS 8 中被破坏了...... @JohnKakon 您可以使用AFHTTPRequestOperationManager,它是使用 NSURLConnection 为其网络调用提供动力的 AFNetworking 类。 @SamYoungNY 这在 8.3 中仍然存在问题。 在 iOS 9.2 中可能更早修复。在 8.4 中坏了。【参考方案2】:

NSURLConnection 工作不正常。它将正确存储响应,但它在 iOS 8.0 上never purges the cache(忽略磁盘容量),因此缓存将grow without limit,尽管手动清除缓存确实有效。这是fixed in iOS 8.1,尽管 removeCachedResponseForRequest: 仍然不起作用。

此外,如果您指定的缓存大小小于 5 兆,则它不会缓存任何内容。

【讨论】:

【参考方案3】:

NSURLCacheNSURLSession 都是错误的。 即使您为请求设置了NSURLRequestReturnCacheDataElseLoad,iOS 也可能会尝试从服务器重新加载文件。 例如,当缓存的响应具有 Vary 标头时,就会发生这种情况。 另请注意该方法

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

使用请求中的User-Agent 标头来区分缓存对象。 这意味着如果你通过 NSURLSession 和 UIWebView 访问相同的文件,iOS 会存储两次,因为User-Agent 是不同的。

【讨论】:

以上是关于iOS 8 是不是破坏了 NSURLCache?的主要内容,如果未能解决你的问题,请参考以下文章

NSURLConnection 是不是利用了 NSURLCache?

iOS 8 beta 5 中的今日扩展的 NSUserDefaults 是不是被破坏?

iOS 中 UIWebview 的 NSURLCache

NSURLCache内存缓存

NSURLCache详解和使用

NSURLCache详解和使用