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
(使用您自己创建的NSURLSessionConfiguration
和NSURLCache
)也无法解决此问题。目前,如果您非常需要缓存响应,则必须使用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】:NSURLCache
和 NSURLSession
都是错误的。
即使您为请求设置了NSURLRequestReturnCacheDataElseLoad
,iOS 也可能会尝试从服务器重新加载文件。
例如,当缓存的响应具有 Vary
标头时,就会发生这种情况。
另请注意该方法
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
使用请求中的User-Agent
标头来区分缓存对象。
这意味着如果你通过 NSURLSession 和 UIWebView 访问相同的文件,iOS 会存储两次,因为User-Agent
是不同的。
【讨论】:
以上是关于iOS 8 是不是破坏了 NSURLCache?的主要内容,如果未能解决你的问题,请参考以下文章
NSURLConnection 是不是利用了 NSURLCache?