【发布时间】:2017-04-19 22:58:01
【问题描述】:
我想确定来自NSURLSessionDataTask 的响应是来自缓存还是来自服务器
我正在从
创建我的NSURLSessionDataTask
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;
【问题讨论】:
标签: ios objective-c caching nsurlsession cache-control
我想确定来自NSURLSessionDataTask 的响应是来自缓存还是来自服务器
我正在从
创建我的NSURLSessionDataTask
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;
【问题讨论】:
标签: ios objective-c caching nsurlsession cache-control
想到两个简单的选择:
[[NSURLCache sharedURLCache] cachedResponseForRequest:request],存储缓存的响应,然后在接收完数据后再次执行此操作,并比较两个缓存的响应是否相同。NSURLRequestReturnCacheDataDontLoad 缓存策略发出初始请求,如果失败,使用更合理的策略发出第二个请求。第一种方法通常更可取,因为第二种方法将返回缓存中存在的数据,即使它是陈旧的。但是,在极少数情况下(例如离线模式),这可能是您想要的,这就是我提到它的原因。
【讨论】:
isEqual,大概。
如果您的信息需求只是出于好奇,您可以在 Xcode 运行时网络指标中查看您的网络使用情况。将策略更改为不同的设置并观察差异。
【讨论】:
如果您想使用缓存,那么禁用客户端上的缓存不是一个好的答案。
如果服务器设置了缓存头(etag, cache-control="no-store"),那么 NSURLSession 将根据来自服务器的 200 / 304 响应重新验证并为您提供缓存/新鲜响应。但是,在您的代码中,无论 NSUrlSession 收到 200 还是 304,您总是会看到 statusCode 200。这是有限制的,因为您可能希望在响应没有改变时跳过解析、重新创建对象等。
我所做的解决方法是在响应中使用 etag 值来确定是否发生了变化
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
NSString *etag = (httpResp && [httpResp isKindOfClass:[NSHTTPURLResponse class]]) ? httpResp.allHeaderFields[@"Etag"] : nil;
BOOL somethingHasChanged = [etag isEqualToString:oldEtag];
【讨论】:
oldEtag?
为了知道 URLSessionDataTask 响应是来自缓存还是来自网络,您必须使用自定义 URLSession 并为其提供URLSessionTaskDelegate,该URLSessionTaskDelegate 必须实现以下方法:
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
您会在metrics 中找到非常有用的信息,尤其是请求的事务指标列表。每个事务指标都有一个属性resourceFetchType,可以是.localCache、.networklLoad、.serverPush 或.unknown。
更多信息在这里:Apple documentation regarding URLSessionTaskDelegate
【讨论】: