iPad 上的 localStorage setItem 无法工作

4

在我的混合应用程序(Phonegap)中,我正在尝试以非常标准的方式写入localStorage:

window.localStorage.setItem("proDB", JSON.stringify(data));

或者

window.localStorage["proDB"] = JSON.stringify(data);

但是在iPad 2(iOS 7.1)的Safari浏览器上无法正常工作。

它不能正常工作,整个应用程序会停止运行。

这里是该iPad的userAgent:enter image description here

你能帮我吗?

谢谢。


它是字符串化还是实际存储数据?也就是说,localStorage.setItem("proDB","foo"); 能够工作吗?你是否超过配额? - epascarello
实际上,stringify 起作用是因为如果我只写 var temp = JSON.stringify(data); console.log(temp); 我会得到字符串显示。所以看起来是 localStorage 函数有问题。我只在 localStorage 中写了一些东西,所以我认为我真的没有达到配额。 - Louis
我仍然有这个问题,有人可以帮我吗?谢谢。 - Louis
2
我也遇到了这个问题。 - RomaValcer
Safari的私密浏览模式很可能是罪魁祸首。把你的调用放在一个try catch中,并打印出错误信息。很可能是超过了配额限制。Safari在私密浏览模式下将配额设置为零。不幸的是,我目前发现支持Safari私密浏览的唯一方法是回退到一个shim。我写了一个你可能会发现有用的:memorystorage。更多详情请查看我的博客文章:介绍MemoryStorage - Stijn de Witt
我也有这个问题。到目前为止还没有解决方案。这个问题不仅在私人浏览模式下,普通模式下也能重现。 - Sacky San
3个回答

8
请检查Safari中是否启用了私密浏览。在Safari的私密浏览模式下,您的配额为零。因此,对localStorage.setItem的所有调用都将抛出超过配额的错误。个人认为这是Safari的巨大失误(因为许多网站会出现问题),但事实就是如此,所以我们必须找到一种解决方法。我们可以通过以下方式来实现:
  1. 检测我们是否拥有一个可用的localStorage
  2. 如果没有,回退到某些替代品。
如果您想了解详细信息,请继续阅读 :) 1:检测功能性本地存储 我目前正在使用此代码来检测本地存储是否可用,并在不可用时回退到shim:
var DB;
try {
  var x = '_localstorage_test_' + Date.now();
  localStorage.setItem(x, x);
  var y = localStorage.getItem(x);
  localStorage.removeItem(x);
  if (x !== y) {throw new Error();} // check we get back what we stored
  DB = localStorage; // all fine
}
catch(e) {
  // no localstorage available, use shim
  DB = new MemoryStorage('my-app');
}

编辑:编写此文后,我已经将该特征检测代码打包。如果您正在使用NPM,可以按以下方式安装storage-available

npm install --save storage-available

然后,您可以在代码中像这样使用它:
if (require('storage-available')('localStorage')) {
    // Yay!
}
else {
    // Awwww.....
}

2. 回退到一个备用对象

一旦我们检测到问题,最简单的处理方法是回退到另一个不会在每次写入时抛出错误的对象。

memorystorage 是我编写的一个小型库,遵循 Web Storage API,但将所有内容都存储在内存中。由于它使用相同的API,您可以将其用作localStorage的替代品,并且一切都可以正常运作(尽管没有数据可以在页面重新加载后保存)。它是开源的,因此可随意使用。

背景信息

有关MemoryStorage和此问题的更多信息,请阅读我关于此主题的博客文章:介绍MemoryStorage


0

我使用Swift2.2通过以下逻辑设置了本地存储键值

let jsStaring = "localStorage.setItem('Key', 'value')"
self.webView.stringByEvaluatingJavaScriptFromString(jsStaring)

-1

你的第一个 setItem 示例是正确的。我不认为你可以使用第二个选项 (localStorage["someKey"] = "someValue")。坚持使用第一个。

你提到了混合应用 - 是 PhoneGap 还是其他框架?在应用程序中你在哪里调用 localStorage.setItem?如果是 PhoneGap,请确保在尝试访问 localStorage 之前,通过 onDeviceReady 确保一切都已加载:

<script type="text/javascript">
   // Wait for PhoneGap to load
   document.addEventListener("deviceready", onDeviceReady, false);

   // PhoneGap is ready
   function onDeviceReady() {
        window.localStorage.setItem("key", "value");
   }
</script>

此外,如果应用程序冻结/停止工作,在我的经验中,这是因为在代码的某个地方访问了未定义的对象。也许尝试通过检查localStorage是否未定义并记录它来进行一些调试?您是否100%确定“setItem”行是失败的位置?Console.log是您的好朋友,证明它吧! :)
if (localStorage === undefined) {
   console.log("oops, localStorage not initialized yet.");
}
else {
   window.localStorage.setItem("proDB", JSON.stringify(data));
   console.log("localStorage available.");
}

1
嗨@dotNetkow,感谢您的回答。我已经尝试了两种语法,但它们都不起作用。我确定框架(Phonegap)在我执行此操作时已加载。我将再次检查和调试,并发布更新。 - Louis
最后一次猜测 - 你确定在localStorage中存储的是字符串吗?只有字符串是允许的。http://wtfjs.com/2013/10/07/Local-storage-limitations - dotNetkow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接