自从升级到iOS 6以来,我们看到Safari的web视图可以自由缓存$。ajax调用。这是在一个PhoneGap应用程序的上下文中,所以它使用Safari WebView。我们的美元。ajax调用是POST方法,我们有缓存设置为false {cache:false},但这仍然发生。我们尝试手动添加一个时间戳到头部,但它没有帮助。

我们做了更多的研究,发现Safari只返回具有静态函数签名的web服务的缓存结果,并且在每次调用之间不会改变。例如,想象一个函数是这样的:

getNewRecordID(intRecordType)

这个函数一遍又一遍地接收相同的输入参数,但它每次返回的数据应该是不同的。

苹果一定是急于让iOS 6运行得令人印象深刻,他们对缓存设置太满意了。有人在iOS 6上看到过这种行为吗?如果是的话,到底是什么原因造成的呢?


我们发现的解决方法是修改函数签名,像这样:

getNewRecordID(intRecordType, strTimestamp)

然后总是传递一个TimeStamp参数,并在服务器端丢弃这个值。这就解决了这个问题。


当前回答

为了解决添加到主屏幕的WebApps的这个问题,需要遵循投票最多的两个解决方案。需要在web服务器上关闭缓存,以防止新的请求继续缓存,并且需要在每个post请求中添加一些随机输入,以便已经缓存的请求能够通过。请参考我的帖子:

iOS6 -有一种方法来清除缓存ajax POST请求的webapp添加到主屏幕?

警告:给那些通过在请求中添加时间戳而没有关闭服务器缓存来实现解决方案的人。如果你的应用被添加到主屏幕,每一个帖子的响应现在都将被缓存,清除safari缓存不会清除它,它似乎不会过期。除非有人有办法清除它,否则这看起来像一个潜在的内存泄漏!

其他回答

这是Baz1nga对答案的更新。因为选项。data不是一个对象,而是一个字符串,我只是把时间戳连接起来:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
  if (originalOptions.type == "post" || options.type == "post") {

    if (options.data && options.data.length)
      options.data += "&";
    else
      options.data = "";

    options.data += "timeStamp=" + new Date().getTime();
  }
});

我希望这能对其他在这个问题上绞尽脑汁的开发人员有所帮助。我发现以下任何一个阻止Safari在iOS 6上缓存POST响应:

在请求头中添加[cache-control: no-cache] 添加一个可变URL参数,如当前时间 在响应头中添加[pragma: no-cache] 在响应头中添加[cache-control: no-cache]

我的解决方案是以下在我的Javascript(我所有的AJAX请求是POST)。

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

我还在许多服务器响应中添加了[pragma: no-cache]标头。

如果您使用上述解决方案,请注意任何设置为global: false的$.ajax()调用都不会使用在$. ajaxsetup()中指定的设置,因此您将需要再次添加头部。

经过一些调查,发现iOS6上的Safari会缓存没有cache - control头或者“cache - control: max-age=0”的post。

我所发现的防止这种缓存发生在全局级别而不是不得不在服务调用的末尾随机查询字符串的唯一方法是设置“Cache-Control: no-cache”。

So:

No cache - control或Expires headers = iOS6 Safari将缓存 cache - control max-age=0, immediate Expires = iOS6 Safari将缓存 cache - control: no-cache = iOS6 Safari将不缓存

我怀疑苹果在9.5节关于POST的HTTP规范中利用了这一点:

此方法的响应是不可缓存的,除非响应 包括适当的Cache-Control或Expires报头字段。然而, 303(参见其他)响应可用于将用户代理定向到 检索可缓存资源。

所以理论上你可以缓存POST响应…谁知道。但直到现在,还没有其他浏览器制造商认为这是个好主意。但是,当没有设置Cache-Control或Expires头时,这并不考虑缓存,只有当有一些设置时。所以这一定是个漏洞。

下面是我在Apache配置的正确位中使用的东西,以针对整个API,因为它发生时,我实际上不想缓存任何东西,甚至是get。我不知道的是如何设置这只是POSTs。

Header set Cache-Control "no-cache"

更新:刚刚注意到,我没有指出,只有当POST是相同的,所以改变任何POST数据或URL,你是好的。你可以在其他地方添加一些随机数据到URL或一些POST数据。

更新:在Apache中,如果你想,你可以将“无缓存”限制为post:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST

虽然添加缓存破坏者参数使请求看起来不同,这似乎是一个可靠的解决方案,但我不建议这样做,因为它会损害任何依赖于实际缓存发生的应用程序。使api输出为正确的头是可能的最佳解决方案,即使这比向调用者添加缓存破坏者稍微困难一些。

这个JavaScript代码片段与jQuery和jQuery Mobile一起工作:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});

只需将它放在JavaScript代码中的某个地方(在加载jQuery之后,最好在执行AJAX请求之前),它就会有帮助。