2016-09-06 16 views
2

NSURLCacheを直接クエリするとキャッシュされた応答が表示されますが、同じリソースをNSURLSession:dataTaskWithRequestで要求すると、常にサーバーに照会され、インターネットが無効の場合でもキャッシュレスポンスは表示されません。キャッシュされた応答を使用しないNSURLSession

私はこのようなapplication:didFinishLaunchingWithOptionsNSURLCacheを設定します。その後、私はキャッシュをチェックし、応答を取得するために、このコードを使用しています

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

ご覧のとおり、キャッシュ制御ヘッダーはサーバーはキャッシュを許可するように設定されています。私は私の要求に特別なことはしていません。ちょうどURLを持つデフォルトのNSURLRequestを作成しています。リクエストをトリガするたびに、新しいレスポンスがキャッシュされますが、それ以降のリクエストでは取得されません。

NSURLSessionNSURLCacheに格納された応答を使用しない理由はありますか? NSURLSessionにキャッシュ内のリクエストを実際に検索するように指示する必要がありますか?

答えて

6

キャッシュが参照されていない理由を私は絶対確実にあなたを伝えることはできませんが、私はあなたの最も可能性の高い理由のリストを与えることができます。

  • 照会するとき、サーバーが304で応答しませんでしたそのETagヘッダー(HEAD要求を使用するIIRC)の妥当性について。
  • 要求が大きすぎます。これは、バッファのサイズに比べて、または絶対的に大きなものです。キャッシュは、通常キャッシュする要求より少なくとも数桁大きいはずです。キャッシュサイズの約5%を超えるものはキャッシュされません。
  • リクエストメソッドはGET以外です。 (あなたが機械で猿を大きく飛ばさない限り、GET要求のみがキャッシュされます)
  • 10分以上経過しています(600秒はあまり長くありません)。
  • 要求は、異なるバッキングキャッシュを持つ別のURLセッションで行われました。
  • 一時的なURLセッションまたは他の何らかの理由でキャッシュがないセッションでリクエストが行われました。
  • セッションは実際にキャッシュされた応答を返していますが、予想よりも積極的に再検証しているため、要求が表示されています。
  • あなたのURLリクエストは、キャッシュを尊重しないカスタムNSURLProtocol(バックグラウンドで処理されるようになっています。たとえば、誤って動作しているサードパーティ製のネットワーキングまたは広告フレームワークのためです)。
  • 要求を取得しようとしたときに、要求が実際にキャッシュに完全に書き込まれていない(複数のスレッドによって発生したタイミング競合)。

私はおそらくいくつかを忘れています。それは、私がそれらを忘れていると言えば、おそらくそれは文書化されていないということです。

So ...

上記の内容がすべて正常に動作していることを確認した場合は、bugreporter.apple.comにバグを報告し、問題を再現するのに十分なコードと、可能であればパケットダンプを含めてください。

+0

ありがとうございました。フロントエンドのエンジニアとして、ネットワークの問題が発生する可能性があるすべての場所を把握することは非常に困難です。クライアントの設定に関する問題を解消するためにTVDB URLを打つことを試みました。そのためにキャッシュが機能するので、ETagの再検証に問題があると思われます。 – NewShelbyWoo

+0

ETag検証中にサーバーが304を送信していないことが判明しました。チャールズの代理人と確認して修正しました。私は、応答が古くなる前にクライアントが検証を試みることに気づいていませんでした。 – NewShelbyWoo

+0

ニート。喜んで助けた。 – dgatwood

関連する問題