LoginSignup
31
30

More than 5 years have passed since last update.

iOSのlocalStorageは非同期でディスクに保存されるっぽい

Posted at

iOSブラウザの localStorage の検証をしてたら、思わぬ挙動に遭遇したのでまとめてみました。

検証結果から分かったのは、iOSのブラウザにて localStorage.setItem() で保存した内容は、 メモリ上には同期処理ですぐに反映されますが、ハードディスクへの反映は非同期で行われているっぽい という事でした。
ハードディスクへの反映には時間が掛かるらしく、大量にデータを設定した後にすぐにブラウザアプリを落としてしまうと、保存したデータに抜けが発生してしまいます。


検証用サンプル

localStorage test for iOS

今回のサンプルでは、 setInterval() を使って50ミリ秒ごとに複数回 localStorage.setItem() を呼び出してデータを保存しています。

var PREFIX_KEY = "_";
var currentNum = 0; // 現在の番号
var incrementNum = 100; // 一度に保存する件数 (1 or 10 or 100)

setInterval(setItems, 50);

function setItems(){
    var i;
    for (i=0;i<incrementNum;i++) {
        id = i + currentNum;
        localStorage.setItem(PREFIX_KEY + id.toString(), "1"); // 値は常に"1"
        if (id == 999) {
            // 処理を打ち切り
        }
    }
}

localStorage.setItem() で使用するキーは"_xxx"の形式になっていて、xxxの箇所は0から999までの範囲で合計1000件を保存できるようになっています。
また、1回の処理で保存できる件数は1、10、100から選べるようになっています。


検証結果

検証に使用した環境は以下の通りです。
・iPhone5 / iOS 7.1.1 / Safari

これを使用して100件ずつ保存してみます。
1000件分を保存するには10回呼び出す必要があるので、0.5秒程で呼び出し処理が完了します。


localStorageに1000件保存した結果

localStorageに1000件保存した結果

この時点で、 localStorage.length はちゃんと1000になっています。
また、 localStorage.getItem() を使って1個ずつ値をチェックしてみても、ちゃんと全てのキーに値が入っているようです。


アプリ再起動後

この後、すぐにSafariアプリを落として再起動します。

アプリ再起動後

何故か localStorage.length の値が400に減っていて、実際の中身も所々が抜けてしまっているようです。
一応、 length の数と getItem() でチェックした有効数は一致していました。

ちなみに、 今回の環境では約8秒待った後であれば1000件分のデータがちゃんと保持されている 事が確認取れています。


他に調べたこと

  • iPhone3GS(iOS6.1.3)やiPad AIR(iOS7.1.1)でも同じような現象を確認
  • SO-03D(Android 4.0)では起きてないっぽい
  • 50ミリ秒に10件ずつの場合、再起動後に700件ぐらい保持
  • 50ミリ秒に1件ずつの場合、再起動後でも確実に1000件保持


まとめ

この検証結果から考えると、一度にかなりの量のデータを保存しない限りは問題なさそうですが、データが抜けてしまう可能性があるのは要注意ですね。
ではでは。

31
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
30