在iPhone和iOS 7上使用LocalStorage会抛出这个错误。我一直在寻找一个解决方案,但考虑到我甚至没有私下浏览,没有什么相关的。

我不明白为什么在iOS 7默认禁用localStorage,但它似乎是?我也在其他网站上测试过,但没有成功。我甚至尝试使用http://arty.name/localstorage.html这个网站来测试它,但由于一些奇怪的原因,它似乎根本没有保存任何东西。

有没有人遇到过同样的问题,只是他们很幸运地解决了它?我应该改变我的存储方法吗?

我试图通过只存储几行信息来硬调试它,但没有用。我使用标准的localStorage.setItem()函数保存。


当前回答

下面是一个扩展的解决方案,基于上面DrewT的答案,如果localStorage不可用,则使用cookie。它使用Mozilla的docookie库:

function localStorageGet( pKey ) {
    if( localStorageSupported() ) {
        return localStorage[pKey];
    } else {
        return docCookies.getItem( 'localstorage.'+pKey );
    }
}

function localStorageSet( pKey, pValue ) {
    if( localStorageSupported() ) {
        localStorage[pKey] = pValue;
    } else {
        docCookies.setItem( 'localstorage.'+pKey, pValue );
    }
}

// global to cache value
var gStorageSupported = undefined;
function localStorageSupported() {
    var testKey = 'test', storage = window.sessionStorage;
    if( gStorageSupported === undefined ) {
        try {
            storage.setItem(testKey, '1');
            storage.removeItem(testKey);
            gStorageSupported = true;
        } catch (error) {
            gStorageSupported = false;
        }
    }
    return gStorageSupported;
}

在你的源代码中,只需使用:

localStorageSet( 'foobar', 'yes' );
...
var foo = localStorageGet( 'foobar' );
...

其他回答

我碰巧在iOS 7中遇到了同样的问题(有些设备没有模拟器)。

看起来iOS 7中的Safari有一个更低的存储配额,这显然是通过拥有一个很长的历史日志来达到的。

我认为最好的实践是捕获异常。

Modernizr项目有一个简单的补丁,你应该尝试类似的东西:https://github.com/Modernizr/Modernizr/blob/master/feature-detects/storage/localstorage.js

下面是一个扩展的解决方案,基于上面DrewT的答案,如果localStorage不可用,则使用cookie。它使用Mozilla的docookie库:

function localStorageGet( pKey ) {
    if( localStorageSupported() ) {
        return localStorage[pKey];
    } else {
        return docCookies.getItem( 'localstorage.'+pKey );
    }
}

function localStorageSet( pKey, pValue ) {
    if( localStorageSupported() ) {
        localStorage[pKey] = pValue;
    } else {
        docCookies.setItem( 'localstorage.'+pKey, pValue );
    }
}

// global to cache value
var gStorageSupported = undefined;
function localStorageSupported() {
    var testKey = 'test', storage = window.sessionStorage;
    if( gStorageSupported === undefined ) {
        try {
            storage.setItem(testKey, '1');
            storage.removeItem(testKey);
            gStorageSupported = true;
        } catch (error) {
            gStorageSupported = false;
        }
    }
    return gStorageSupported;
}

在你的源代码中,只需使用:

localStorageSet( 'foobar', 'yes' );
...
var foo = localStorageGet( 'foobar' );
...

我使用这个返回true或false的简单函数来测试localStorage的可用性:

isLocalStorageNameSupported = function() {
    var testKey = 'test', storage = window.sessionStorage;
    try {
        storage.setItem(testKey, '1');
        storage.removeItem(testKey);
        return true;
    } catch (error) {
        return false;
    }
}

现在您可以在使用localStorage.setItem()之前测试它的可用性。例子:

if ( isLocalStorageNameSupported() ) {
    // can use localStorage.setItem('item','value')
} else {
    // can't use localStorage.setItem('item','value')
}

正如在其他回答中已经解释过的那样,当处于私有浏览模式时,Safari在尝试使用localStorage.setItem()保存数据时总是会抛出这个异常。

为了解决这个问题,我写了一个模仿localStorage的假localStorage,包括方法和事件。

伪localStorage: https://gist.github.com/engelfrost/fd707819658f72b42f55

这可能不是解决这个问题的好办法。对于我的场景来说,这是一个很好的解决方案,因为替代方案是对已经存在的应用程序进行重大重写。

2017年4月,一个补丁被合并到Safari中,因此它与其他浏览器保持一致。它随Safari 11一起发布。

https://bugs.webkit.org/show_bug.cgi?id=157010