iOS“Web App”与Mobile Safari具有不同的localStorage

时间:2012-07-18 15:40:58

标签: ios web-applications local-storage fullscreen iphone-standalone-web-app

我有一个带有元标记的iPad的webapp:

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

当我从主页(支持网络应用程序的版本)打开应用程序或在Mobile Safari中输入地址时,localStorage的内容会有所不同。我已通过打印location.href确认地址相同。

使用移动版Safari时对localStorage所做的所有更改都反映在支持Web应用程序的版本中,但在支持Web应用程序的版本中所做的更改不会反映在Mobile Safari版本中。

域名相同,localStorage应该相同。世界上到底发生了什么?这可以修复吗?


更新 - 解决方案:根据接受的答案提示#2(强制用户处于全屏模式),我添加了以下代码:

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

因此,如果您使用的浏览器支持独立模式,并且您不处于独立模式,请重定向到页面(instructions.html),该页面向用户显示如何将应用程序添加到主屏幕。

感谢大家的投入!

3 个答案:

答案 0 :(得分:26)

<强>要点:

Safari和全屏网络应用程序(支持网络应用程序)具有localStorage数据的单独内存中直写高速缓存。每次全屏应用程序变为活动状态时,它都会从磁盘重新加载localStorage(允许它查看Safari的更改)。但是,当Safari变为活动状态时,它不会从磁盘重新加载localStorage数据,因此除非您杀死Safari并重新启动它,否则它不会在全屏应用程序中看到更改。

完整说明:

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

  1. 缓存失效
  2. 命名事物
  3. off-by-one errors
  4. localStorage中的错误行为是问题#1的结果。原因如下:

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

    问题是全屏网络应用程序(让我们称之为FSWA)使用iOS浏览器引擎的单独实例,虽然FSWA在磁盘上为localStorage数据共享相同的位置,但它没有与Safari共享localStorage数据的内存缓存。

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

    这是幕后的......

    1. 用户进行更改,将数据写入Safari中的localStorage
    2. Safari将数据写入Safari的内存中localStorage缓存
    3. Safari将localStorage数据从缓存刷新到磁盘
    4. 用户离开safari并启动FSWA
    5. FSWA从磁盘加载和读取localStorage数据到内存缓存
    6. 用户可以在Safari
    7. 中查看已更改的数据(步骤1中)
    8. 用户在将数据写入localStorage
    9. 的FSWA中进行更改
    10. FSWA将数据写入其localStorage缓存(Safari的缓存未更新)
    11. FSWA将其localStorage缓存数据刷新到磁盘
    12. 用户切换回Safari
    13. Safari已在运行,并且不会从磁盘重新加载localStorage数据
    14. Safari从其现有的内存缓存中读取旧数据
    15. 用户未看到在步骤#7中进行的更改
    16. 为证明这一点,您可以在步骤#4和步骤#10之间kill Safari。然后,当您在步骤#11中重新启动Safari时,它将从磁盘重新加载localStorage,您将看到FSWA写入的数据。

答案 1 :(得分:5)

在iOS5中,我能够在同一个域上拥有两个能够看到彼此的localStorage的全屏网络应用程序。这克服了全屏和Safari之间的差异。

然而,对于iOS6,我必须将我的两个全屏网络应用程序合并到一个应用程序。

答案 2 :(得分:3)

假设您正确保存本地存储数据,如果我没有弄错的话,您在网络应用开发者中遇到的有些常见问题。 Cookie,会话和本地存储似乎以不同方式存储在“网络应用”(从主屏幕启动)到通过移动版Safari保存的数据中。

我过去对此进行了一些相当彻底的测试,并且在我看来,没有足够好的解决方法。仅举几个例子,我和我的同事遇到了类似的问题:在我们最近开发的Web应用程序中,用户必须先登录才能访问其所有功能。如果通过移动safari登录然后切换到应用程序的下载版本,则需要登录,但情况并非总是如此。通常需要再次登录,建议cookie可以存储在不同的“数据库”中,具体取决于您选择启动应用程序的方式或位置。

此外,正如凯文所说,还有更多,而不仅仅是不同的数据库。通过主屏幕启动的应用似乎打开得更慢,主屏幕应用程序在启动时总是重新加载,表明没有多任务支持等。我的结论:程序启动下载的网络应用程序!= safari减去地址栏,因此不应该这样对待。

虽然Apple 是一个很好的功能,但是主屏幕网络应用程序并没有像预期的那样完美地运行(或者像在safari中打开一样)。在您的情况下,假设您存储LS数据正确并尝试了不同的方法来解决您的特定问题,我建议使用以下替代方法之一:

  1. 使用 mysql 数据库从/到而不是
  2. 强制用户在使用之前下载应用(如this example
  3. 不鼓励用户下载该应用,并假设他们中的大部分都会通过移动版本访问该应用
  4. 接受数据可能不同的事实(根据应用的性质,这可能不适合您)
  5. 采用我的方法,通过Phonegap's内置功能将您的网络应用“转换”为原生应用。如果是这样,请看看Jonathan Stark的this tutorial
  6. 希望这有助于澄清至少部分内容。