localStorage setItem doesn't work on ipad

Louis picture Louis · Mar 20, 2014 · Viewed 8.1k times · Source

In my hydbrid app (Phonegap), I am trying to write to localStorage in a very standard way :

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

or

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

But it doesn't work on Safari on iPad 2 (iOS 7.1).

It doesn't work and the whole app stops.

Here's the userAgent of this ipad : enter image description here

Can you help me ?

Thanks

Answer

Stijn de Witt picture Stijn de Witt · Aug 25, 2015

Please check whether you have Private Browsing enabled in Safari. In Safari Private Browsing mode, you get a quota of zero. Hence, all calls to localStorage.setItem will throw a quota exceeded error. Personally I think this is a huge mistake by Safari (as so many sites break), but it is what it is so we have to find a way around it. We can do this by:

  1. Detecting whether we have a functional localStorage
  2. Falling back to some replacement if not.

Read on if you want the details :)

1: Detecting a functional local storage

I am currently using this code to detect whether local storage is available, and fall back to a shim if not:

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');
}

EDIT: Since writing this I have packaged up the feature detecting code. If you are using NPM you can install storage-available like so:

npm install --save storage-available

then you can use it in your code like this:

if (require('storage-available')('localStorage')) {
    // Yay!
}
else {
    // Awwww.....
}

2. Fall back to a shim

The easiest way to deal with the issue once we have detected the problem is to fall back to some other object that does not throw errors on every write.

memorystorage is a little library I wrote that follows the Web Storage API but just stores everything in memory. Because it uses the same API, you can use it as a drop-in replacement for localStorage and everything will function fine (though no data will survive page reload). It's Open Source so use as you please.

Background info

For more information on MemoryStorage and this issue in general, read my blog post on this topic: Introducing MemoryStorage.