如何知道NSURLSessionDataTask响应是否来自缓存?

时间:2016-12-05 14:06:23

标签: ios objective-c caching nsurlsession cache-control

我想确定来自NSURLSessionDataTask的回复是来自缓存还是来自服务器

我正在从

创建NSURLSessionDataTask
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;

4 个答案:

答案 0 :(得分:4)

我想到了两个简单的选择:

  • 在发出请求之前调用[[NSURLCache sharedURLCache] cachedResponseForRequest:request],存储缓存的响应,然后在完成接收数据后再次执行此操作,并比较两个缓存的响应以查看它们是否相同。
  • 使用NSURLRequestReturnCacheDataDontLoad缓存策略发出初始请求,如果失败,请使用更合理的策略发出第二个请求。

第一种方法通常更可取,因为第二种方法将返回缓存中存在的数据,即使它是陈旧的。但是,在一些罕见的情况下(例如离线模式),这可能就是你想要的,这就是我提到的原因。

答案 1 :(得分:1)

如果您的信息需求仅仅是出于好奇,您可以在Xcode运行时网络中查看您的网络使用情况。将策略更改为其他设置并观察差异。

答案 2 :(得分:1)

如果要使用缓存,那么在客户端上禁用缓存不是一个好的答案。

如果服务器设置了缓存头(etag,cache-control =“ no-store”),则NSURLSession将基于服务器的200/304响应重新验证并为您提供缓存/新鲜响应。但是,在您的代码中,无论NSUrlSession收到200还是304,您始终会看到statusCode200。这是有限制的,因为当响应没有更改时,您可能希望跳过解析,重新创建对象等。

我所做的解决方法是,在响应中使用etag值来确定是否已更改

NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
NSString *etag = (httpResp && [httpResp isKindOfClass:[NSHTTPURLResponse class]]) ? httpResp.allHeaderFields[@"Etag"] : nil;
BOOL somethingHasChanged = [etag isEqualToString:oldEtag];

答案 3 :(得分:0)

为了知道 URLSessionDataTask 响应是来自缓存还是来自网络,您必须使用自定义 URLSession 并为其提供一个 URLSessionTaskDelegate,该 func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) 必须实现以下方法:

metrics

您会在 resourceFetchType 中找到非常有用的信息,尤其是请求的交易指标列表。每个事务指标都有一个属性 @c6o/kubelcient,它可以是 .localCache、.networklLoad、.serverPush 或 .unknown。

此处的更多信息:Apple documentation regarding URLSessionTaskDelegate