iOS的“Web应用程序”与Mobile Safari有不同的localStorage

我有一个与meta标签的iPad的webapp:

<meta name="apple-mobile-web-app-capable" content="yes"> 

当我从主页(支持networking应用程序的版本)打开应用程序或在Mobile Safari中input地址时,localStorage的内容不同。 我已经通过打印location.href确认地址是相同的。

移动Safari浏览器对localStorage进行的所有更改都反映在支持Web应用程序的版本中,但支持Web应用程序的版本所做的更改未反映在Mobile Safari版本中。

域是相同的,localStorage应该是相同的。 世界正在发生什么? 这可以解决吗?


更新 – 解决scheme :从接受的答案(迫使用户进入全屏模式)的build议#2我添加了这一点的代码:

 if(("standalone" in window.navigator) && !window.navigator.standalone) window.location = "instructions.html"; 

因此,如果您使用的是支持独立模式的浏览器,并且您没有处于独立模式,请将其redirect到一个页面(instructions.html),该页面向用户显示如何将该应用添加到主屏幕。

感谢大家的意见!

概要:

Safari和全屏Web应用程序(也称为Web应用程序)具有localStorage数据的单独内存直写caching。 每次全屏应用程序激活时,它会从磁盘重新加载localStorage(允许它看到Safari的更改)。 但是,当Safari变为活动状态时,不会从磁盘重新加载localStorage数据,因此除非您杀死Safari并重新启动,否则将无法在全屏应用程序中看到所做的更改。

完整说明:

计算机科学只有两个难题:

  1. caching失效
  2. 命名的东西
  3. 逐个错误

localStorage中的错误行为是问题#1的结果。 原因如下:

当iOS浏览器引擎加载时,它从磁盘读取localStorage的数据并将其caching在内存中。 然后每次读取数据(例如getItem ),数据都从内存中读取,而不是从磁盘读取; 在写入数据(例如setItem )时,数据被写入内存,然后(asynchronous)刷新到磁盘。 由于localStorage是同步的,这个实现是完全合理的。 如果所有的读写操作都进入磁盘,则每个读写操作都会阻止您的JavaScript执行昂贵的磁盘IO。

问题是,一个全屏的web应用程序(我们称之为FSWA)使用一个单独的iOS浏览器引擎实例,虽然FSWA在localStorage数据上共享磁盘上的相同位置,但它不共享内存中caching使用Safari的localStorage数据。

当您添加FSWA完全重新加载(这意味着localStorage数据从磁盘重新加载)的事实,每次他们成为活动的应用程序时,您将看到您所看到的行为。

这是幕后…

  1. 用户做了一个改变,将数据写入Safari的localStorage
  2. Safari将数据写入Safari的内存localStoragecaching
  3. Safari将localStorage数据从caching刷新到磁盘
  4. 用户离开Safari并启动FSWA
  5. FSWA从磁盘加载并读取localStorage数据到内存中
  6. 用户将看到Safari中已更改的数据(步骤#1)
  7. 用户在将数据写入localStorage的FSWA中进行更改
  8. FSWA将数据写入本地存储caching(Safari的caching未更新)
  9. FSWA将其本地存储caching数据刷新到磁盘
  10. 用户切换回Safari
  11. Safari已经在运行,并且不会从磁盘重新加载localStorage数据
  12. Safari从其现有的内存caching中读取旧数据
  13. 用户不会看到步骤#7中所做的更改

为了certificate这一点,你可以在步骤#4和步骤#10之间杀死Safari 。 然后,当您在步骤#11中重新启动Safari时,它将从磁盘重新加载localStorage,您将看到由FSWA写入的数据。

在iOS5中,我可以在同一个域中看到两个全屏Web应用程序,它们可以看到对方的localStorage。 这克服了全屏和Safari之间的差异。

但是,在iOS6中,我不得不将两个全屏Web应用程序合并到一个应用程序中。

假设你正确保存本地存储数据,如果我没有弄错,你遇到的是一个Web应用程序开发人员常见的问题 。 Cookies,会话和本地存储在“networking应用程序”(从主屏幕启动)中似乎以不同方式存储到通过移动Safari浏览器保存的数据中。

过去我已经做了一些相当彻底的testing,在我看来,没有任何解决方法足够好 。 举个例子,我的同事和我面临着类似的问题:在我们最近开发的一个networking应用程序中,用户必须先login才能访问其所有function。 如果通过移动Safari浏览器login,然后切换到应用程序的下载版本,则预计会login,但情况并非总是如此。 通常需要再次login,这意味着Cookie可能存储在不同的“数据库”中,具体取决于您select启动应用程序的方式或方式。

而且,正如Calvin所说,除了不同的数据库外, 还有更多的东西。 通过主屏幕启动的应用程序似乎打开更慢,主屏幕上的应用程序总是重新加载,当启动时提示没有多任务支持等。 我的结论:程序启动下载的networking应用!= Safari浏览器减去地址栏,因此不应该被视为。

虽然苹果的一个很好的function ,主屏幕的networking应用程序没有像预期的那样执行,或者像人们希望的那样(就像在safari中打开一样)。在你的情况下,假设你正确地存储LS数据并尝试了不同的方法来修复特别的问题, 我会build议以下方法之一:

  1. 使用mysql数据库从/到r / w来代替
  2. 强制用户在使用之前下载应用程序 (如本例中所示 )
  3. 不要鼓励用户下载应用程序,并假设他们大部分将从移动Safari浏览器访问它
  4. 接受数据可能不同的事实 (这可能不是您的替代scheme,具体取决于您的应用程序的性质)
  5. 以我的方法,通过Phonegap的内置function将您的networking应用程序“转换”为本机应用程序 。 如果是这样,请看Jonathan Stark的这篇教程 。

希望这有助于澄清至less部分。