ios - NSURLSession 不使用缓存响应

标签 ios nsurlsession nsurlcache

当我直接查询 NSURLCache 时,我能够看到缓存的响应,但是当我通过 NSURLSession:dataTaskWithRequest 请求相同的资源时,它总是查询服务器并且从不给我缓存响应,即使禁用互联网也是如此。

我在 application:didFinishLaunchingWithOptions 中配置 NSURLCache 如下:

let URLCache = NSURLCache(memoryCapacity: 20 * 1024 * 1024,
                          diskCapacity: 80 * 1024 * 1024, diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)

然后我使用这段代码检查缓存并获取响应:

print("cached response is \(NSURLCache.sharedURLCache().cachedResponseForRequest(request)?.response)")

NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
  print("nsurlsession response \(response)")
}.resume()

我的调试打印结果是:

cached response is Optional(<NSHTTPURLResponse: 0x7f809d0ddfe0> { URL: https://api.test.com/stuff } { status code: 200, headers {
"Cache-Control" = "public, s-maxage=600";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Tue, 06 Sep 2016 23:41:24 GMT";
Etag = "\"4800a836fee27c56a3cce1f0f2bddaefa5a7785b\"";
Server = "nginx/1.11.3";
"Transfer-Encoding" = Identity;
"X-RateLimit-Limit" = 60;
"X-RateLimit-Remaining" = 2; } })

nsurlsession response Optional(<NSHTTPURLResponse: 0x7f809d202e50> { URL: https://api.test.com/stuff } { status code: 200, headers {
"Cache-Control" = "public, s-maxage=600";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Tue, 06 Sep 2016 23:51:52 GMT";
Etag = "\"4800a836fee27c56a3cce1f0f2bddaefa5a7785b\"";
Server = "nginx/1.11.3";
"Transfer-Encoding" = Identity;
"X-RateLimit-Limit" = 60;
"X-RateLimit-Remaining" = 52; } })

如您所见,服务器的 Cache-Control header 设置为允许缓存。我没有对我的请求做任何特殊的事情,只是创建一个带有 URL 的默认 NSURLRequest。每次我触发请求时,新的响应都会被缓存,但它永远不会在后续请求中检索到。

NSURLSession 不使用存储在 NSURLCache 中的响应有什么原因吗?我必须做些什么来告诉 NSURLSession 在缓存中实际查找请求吗?

最佳答案

我不能绝对肯定地告诉您为什么没有查询缓存,但我可以给您列出最可能的原因:

  • 当查询该 ETag header 的有效性时,服务器没有以 304 响应(IIRC 使用 HEAD 请求)。
  • 请求太大——无论是相对于缓冲区的大小还是绝对值。缓存至少应该比您通常缓存的请求大几个数量级;超过缓存大小 5% 的任何内容都不会被缓存。
  • 请求方法不是 GET。 (只有 GET 请求才会被缓存,除非你对机器进行大量操作。)
  • 10 多分钟过去了(600 秒不是很长)。
  • 请求是在具有不同后备缓存的不同 URL session 中发出的。
  • 请求是在临时 URL session 或由于某些其他原因没有缓存的 session 中发出的。
  • session 实际上正在返回缓存的响应,但您看到的是一个请求,因为它重新验证的速度比您预期的要快一些——可能是因为它很快就会达到其最大期限。
  • 您的 URL 请求正在后台由不考虑缓存的自定义 NSURLProtocol 处理(例如,由于某些行为不当的第三方网络或广告框架)。
  • 当您尝试检索请求时,该请求实际上并未完全写入缓存(多线程导致的时间竞争)。

我可能忘记了其他几个。话虽如此,如果我忘记了它们,那可能意味着它们没有记录在案。

所以...

如果您确认上面列出的一切都按预期工作,请在 bugreporter.apple.com 提交错误并包含足够的代码来重现问题,如果可能的话还包括数据包转储。

关于ios - NSURLSession 不使用缓存响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39359451/

相关文章:

ios - NSURLResponse 返回内容范围,忽略我要求的范围

ios - NSURLCache 真的如本文所述需要初始化吗?

ios - 是否可以 "pause"线程并让另一个操作先进行?

ios - 来自 Xcode 8.2.1 的应用商店应用提交

ios - 在 UITextview 中显示响应时出错

Swift 2 iOS 9 Do Catch 尝试崩溃并发现意外的 nil

ios - 如何使用缓存使用 SfSafariView 或 WKWebView 更快地加载网站?

ios - libsqlite3.dylib 和 libsqlite3.0.dylib 有什么区别?

swift - 从 Swift NSURLsession 的 Rest API 调用返回数据

ios - 将 AlamofireImage 响应缓存到磁盘