NSURLCache缓存不应缓存的随机响应

时间:2013-09-02 09:43:58

标签: ios caching nsurlconnection afnetworking nsurlcache

我正在实施一个应用程序,它可以对我们也控制的rest-api进行大量的网络调用。最近我们决定在服务器端引入缓存头,以节省一些宝贵的网络和服务器时间。由于我们事先不知道数据有效期多长,我们不会发送Cache-control: max-ageExpires标头,我们所做的只是发送Last-Modified标头和{{1}所以我们总是点击服务器,但是大多数情况下使用E-tag的响应非常快。 一开始似乎一切正常,许多请求都被缓存了。但是,由于缓存,我在应用上遇到了一些随机数据错误

出于某些原因,我无法理解,在某些时候,请求被本地缓存并用作“更新”数据,而不是命中服务器,而实际上并非如此。问题一直存在,直到一段时间过去。然后,所有内容都会再次正常运行到服务器,就像使用304标头一样,但没有它!所以,我的问题是:


cache-controlNSURLCache标头未附带原始请求时,NSURLConnectionCache-control: max-age一起决定某个特定请求无需上线的情况如何?有谁经历过类似的影响?如何在不删除整个缓存的情况下解决它?


更多背景信息:

  • 我正在使用AFNetworking,但它依赖于Expires所以我没有 认为它改变了什么
  • 使用的缓存是默认的NSURLConnection实例
  • 这是[NSURLCache sharedURLCache]请求,当我从缓存的响应中检查标头时,这就是我得到的:

    GET

    po [response allHeaderFields]
  • 我无法预测或重现何时会发生错误,因此无法选择依赖删除缓存的解决方案。

  • 我使用的是iOS5 +

3 个答案:

答案 0 :(得分:4)

  

NSURLCache如何与NSURLConnection一起决定a   当...时,特殊要求不需要上线。

RFC 2616第13.2节说:

  

由于源服务器并不总是提供明确的到期时间,   HTTP缓存通常分配启发式到期时间,使用   使用其他标头值的算法(例如Last-Modified   时间)估计合理的到期时间。 HTTP / 1.1   规范没有提供具体的算法,但确实强加了   对结果的最坏情况限制。自启发式到期   时间可能会损害语义透明度,他们应该使用它们   谨慎,我们鼓励原始服务器提供明确的   到期时间尽可能多。

因此,即使您没有为数据提供特定的生命周期,URL加载系统也可以确定缓存的数据“足够新鲜”。

为获得最佳效果,您应尝试在响应标头中提供特定的生命周期。如果无法添加这样的标头,也许您可​​以改变请求。 if-modified-sincecache-control可以帮助您避免缓存数据。

答案 1 :(得分:2)

根据声明“在某些时候,请求被本地缓存并用作”更新“数据而不会访问服务器”我很确定您的请求是内存缓存的。

NSURLCache将数据缓存在内存中。不在磁盘上所以让我解释一下你可能会发生什么。

您启动了该应用。 进行Web服务调用 它从服务器获取数据 你再次拨打电话,它从内存中获取响应而不调用服务器并显示结果。

您离开应用程序一段时间或重新启动应用程序。它会检查数据是否在内存中。如果它不可用,那么它再次调用服务器并重复相同的行为。

我建议您为自己编写自己的磁盘缓存,而不是依赖NSURLConnection和NSUrlCache。因为某些缓存策略还没有从Apple实现。

答案 2 :(得分:2)

请确保您的NSURLRequest缓存策略设置为NSURLRequestReturnCacheDataElseLoad

如果你在AFHTTPClient.m中使用AFNetworking,你可以覆盖方法

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                  path:(NSString *)path
                            parameters:(NSDictionary *)parameters

用这个

替换第470行
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:15];

你实际做的是告诉加载缓存的请求如果服务器没有更新..如果服务器更新,那么它将忽略缓存并从服务器下载内容

仅供参考:NSURLCache将数据存储在内存中。如果您想将数据存储在光盘中,可以在此处使用我的课程

https://github.com/shoeb01717/Disc-Cache-iOS