Update (2016-11-01)
I was using AmplifyJS mentioned below to work around this issue. However, for Safari in Private browsing, it was falling back to a memory-based storage. In my case, it was not appropriate because it means the storage is cleared on refresh, even if the user is still in private browsing.
Also, I have noticed a number of users who are always browsing in Private mode on iOS Safari. For that reason, a better fallback for Safari is to use cookies (if available). By default, cookies are still accessible even in private browsing. Of course, they are cleared when exiting the private browsing, but they are not cleared on refresh.
I found the local-storage-fallback library. From the documentation:
Purpose
With browser settings like "Private Browsing" it has become a problem to rely on a working window.localStorage, even in newer browsers. Even though it may exist, it will throw exceptions when trying to use setItem or getItem. This module will run appropriate checks to see what browser storage mechanism might be available, and then expose it. It uses the same API as localStorage so it should work as a drop-in replacement in most cases.
Beware of the gotchas:
- CookieStorage has storage limits. Be careful here.
- MemoryStorage will not persist between page loads. This is more or less a stop-gap to prevent page crashes, but may be sufficient for websites that don't do full page loads.
TL;DR:
Use local-storage-fallback (unified API with .getItem(prop)
and .setItem(prop, val)
):
Check and use appropriate storage adapter for browser (localStorage, sessionStorage, cookies, memory)
Original answer
To add upon previous answers, one possible workaround would be to change the storage method. There are a few librairies such as AmplifyJS and PersistJS which can help. Both libs allow persistent client-side storage through several backends.
For AmplifyJS
localStorage
- IE 8+
- Firefox 3.5+
- Safari 4+
- Chrome
- Opera 10.5+
- iPhone 2+
- Android 2+
sessionStorage
- IE 8+
- Firefox 2+
- Safari 4+
- Chrome
- Opera 10.5+
- iPhone 2+
- Android 2+
globalStorage
userData
- IE 5 - 7
- userData exists in newer versions of IE as well, but due to quirks in IE 9's implementation, we don't register userData if localStorage
is supported.
memory
- An in-memory store is provided as a fallback if none of the other storage types are available.
For PersistentJS
- flash: Flash 8 persistent storage.
- gears: Google Gears-based persistent storage.
- localstorage: HTML5 draft storage.
- globalstorage: HTML5 draft storage (old spec).
- ie: Internet Explorer userdata behaviors.
- cookie: Cookie-based persistent storage.
They offer an abstraction layer so you don't have to worry about choosing the storage type. Keep in mind there might be some limitations (such as size limits) depending on the storage type though. Right now, I am using AmplifyJS, but I still have to do some more testing on iOS 7/Safari/etc. to see if it actually solves the problem.