NSURLSession不使用缓存的响应

New*_*Woo 2 nsurlcache ios nsurlsession

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

我配置NSURLCacheapplication:didFinishLaunchingWithOptions是这样的:

let URLCache = NSURLCache(memoryCapacity: 20 * 1024 * 1024,
                          diskCapacity: 80 * 1024 * 1024, diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)
Run Code Online (Sandbox Code Playgroud)

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

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

NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
  print("nsurlsession response \(response)")
}.resume()
Run Code Online (Sandbox Code Playgroud)

我的调试打印结果是:

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; } })
Run Code Online (Sandbox Code Playgroud)

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

是否有任何理由NSURLSession不使用存储的响应NSURLCache?有什么我必须要做的事情来NSURLSession实际查找缓存中的请求吗?

dga*_*ood 10

我不能绝对肯定地告诉你为什么没有咨询缓存,但我可以给你一个最可能的原因列表:

  • 当查询该ETag标头(使用HEAD请求的IIRC)的有效性时,服务器没有响应304.
  • 请求太大 - 无论是相对于缓冲区的大小还是绝对值.缓存应至少比您通常缓存的请求大几个数量级; 超过大约5%的缓存大小的任何内容都不会被缓存.
  • 请求方法不是GET.(只有GET请求被缓存,除非你明显地使用机器.)
  • 超过10分钟已经过去(600秒不是很长).
  • 该请求是在具有不同后备缓存的不同URL会话中进行的.
  • 请求是在短暂的URL会话或由于某些其他原因没有缓存的会话中进行的.
  • 该会话实际上正在返回缓存的响应,但是您正在查看请求,因为它会比您预期的更积极地重新验证 - 可能是因为它将很快达到其最大年龄.
  • 您的URL请求将在后台由不受缓存影响的自定义NSURLProtocol处理(例如,由于某些行为不当的第三方网络或广告框架).
  • 当您尝试检索请求时,请求实际上并未完全写入缓存(由多个线程引起的时序竞争).

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

所以...

如果您验证上面列出的所有内容都按预期工作,请在bugreporter.apple.com上提交一个错误,并包含足够的代码来重现问题,并尽可能包含数据包转储.