iOS 'Web App' 的 localStorage 与 Mobile Safari 不同

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

我有一个带有元标记的 iPad 网络应用程序:

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

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

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

域是相同的,localStorage 应该是相同的。这到底是怎么回事?这可以修复吗?


更新 - 解决方案:根据接受的答案中的建议 #2(强制用户处于全屏模式),我添加了这段代码:

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

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

感谢大家的投入!

最佳答案

总结:

Safari 浏览器和全屏网络应用程序(也称为支持网络应用程序)具有单独的本地存储数据内存直写缓存。每次全屏应用程序激活时,它都会从磁盘重新加载 localStorage(允许它看到 Safari 的更改)。但是,当 Safari 激活时,它不会从磁盘重新加载 localStorage 数据,因此除非您终止 Safari 并重新启动它,否则它不会看到在全屏应用程序中所做的更改。

完整说明:

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

  1. 缓存失效
  2. 命名事物
  3. 差一错误

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 将本地存储数据从磁盘加载并读取到内存缓存中
  6. 用户在 Safari 中看到更改的数据(在步骤 #1 中)
  7. 用户在将数据写入 localStorage 的 FSWA 中进行更改
  8. FSWA 将数据写入其 localStorage 缓存(Safari 的缓存未更新)
  9. FSWA 将其 localStorage 缓存数据刷新到磁盘
  10. 用户切换回 Safari
  11. Safari 已经在运行,它不会从磁盘重新加载 localStorage 数据
  12. Safari 从其现有的内存缓存中读取旧数据
  13. 用户看不到在第 7 步中所做的更改

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

关于iOS 'Web App' 的 localStorage 与 Mobile Safari 不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11545149/

相关文章:

javascript - 秒表/计时器,保存变量并显示在高分列表中(HTML,JS)

javascript - 使用 HtmlService 透明的 Google App Script 背景

javascript - 在正文中嵌入 &lt;script&gt; 标签..有什么影响?

android - 如何在Android(SQlite)中将本地存储数据从一台设备传输到另一台设备

javascript - sessionStorage 将所有内容存储在同一个数组中

ios - 是否可以通过app读取UDID?

iOS 与 LTE 通信类似 BLE 交互

ios - 尝试安装 Google 登录时出现链接错误

node.js - 使用 `useLocalStorage` 和 `useDebounce` 时如何解决 Next.js 中的 react-hydration-error

ios - SDK 中是否包含 iPad "page turn"转换?