2016-09-06 3 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 (예 : 잘못 행동 한 타사 네트워킹 또는 광고 프레임 워크로 인해)로 처리되고 있습니다.
  • 요청을 검색하려고 시도했을 때 요청이 실제로 캐시에 완전히 기록되지 않았습니다 (여러 스레드로 인한 타이밍 경쟁).

나는 여러 다른 것을 잊어 버릴 것입니다. 그렇게 말하면, 내가 그들을 잊어 버렸다면, 아마도 그것들이 문서화되어 있지 않다는 것을 의미 할 것이다.

그래서 ...

위에서 나열한 모든 것이 예상대로 작동하는지 확인하는 경우 bugreporter.apple.com에 버그를 신고하고 가능한 경우 패킷 덤프와 함께 문제를 재현 할 수있는 충분한 코드를 포함하십시오.

+0

감사합니다. 매우 유용합니다. 프런트 엔드 엔지니어로서 네트워크 문제가 발생할 수있는 모든 장소를 파악하는 것은 매우 어렵습니다. TVDB url을 사용하여 클라이언트 구성 문제를 제거하려고 시도했는데 캐싱이 작동하므로 ETag 재확인 문제가 의심됩니다. – NewShelbyWoo

+0

ETag 유효성 검사 중에 서버가 304를 보내지 않았습니다. 찰스 프록시와 확인하고 수정했습니다. 응답이 오래되지 않기 전에 클라이언트가 유효성 검사를 시도한다는 것을 알지 못했습니다. – NewShelbyWoo

+0

도움이 된 것을 기쁘게 생각합니다. – dgatwood

관련 문제