2016-09-06 42 views
2

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

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; } }) 

正如你所看到的,来自t的Cache-Control头他的服务器设置为允许缓存。我没有对我的请求做任何特别的处理,只是通过URL创建一个默认的NSURLRequest。每次我触发请求时,新的响应都会被缓存,但在后续请求中永远不会检索到。

NSURLSession是否有任何理由不使用存储在NSURLCache中的响应?我需要做些什么才能告诉NSURLSession实际查找缓存中的请求?

回答

6

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

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

我可能会忘记其他几个人。就这样说,如果我忘了他们,那可能意味着他们没有记录。

所以...

如果验证上面列出按预期工作一切,请通过bugreporter.apple.com一个bug,包括足够的代码来重现问题,用包转储如果可能的话一起。

+0

谢谢你,这是*非常*有帮助。作为一名前端工程师,我很难找出所有可能发生网络问题的地方。我尝试打击TVDB网址以消除客户端配置的问题,并且缓存适用于此,所以我怀疑这个问题与ETag重新验证有关。 – NewShelbyWoo

+0

发现服务器在ETag验证期间没有发送304s。与查尔斯代理验证,并得到修复。我没有意识到客户会在响应失效之前尝试验证。 – NewShelbyWoo

+0

整洁。很高兴这有帮助。 – dgatwood