NSUserDefaultsの罠

アプリの設定や状態を記録しておくのに便利なNSUserDefaultsですが、必ず保存できるとは限りません。そもそもiOSには処理が集中した時に、アラームや着信などの重要な処理を優先させる仕組みになっているため、synchronizeに失敗する場合があります。

と言っても、さほど問題ではありませんが、以下のような場合には注意が必要です。

[[NSUserDefaults standardUserDefaults] setObject:currentArray forKey:@"ListArray"];
[[NSUserDefaults standardUserDefaults] setInteger:selectedIndex forKey:@"ListSelectedIndex"];
[[NSUserDefaults standardUserDefaults] synchronize];

これは閲覧していたリストの「配列」と「何番目が選択されていたかのインデックス」を保存するコードですが、この内の片方だけしか保存されない稀なケースがあります。こうしてset~で複数のデータを記録する場合、配列とそのインデックスの様に相関関係がある場合には、使う際にチェックしないとNSRangeExceptionでクラッシュするかもしれません。

こういった場合、配列とインデックスを1つの配列にまとめてから保存すれば、synchronizeの失敗、イコール、配列とインデックスの両方の保存失敗となって整合性が保てるかもしれません(未確認)。NSUserDefaultsは手軽な反面、データベースの機能が少ないので、重要なデータを扱う場合は、トランザクション機構を備えた別の方法にした方が良い場合もあります。最近だとCore Data以外にもAndroidでも使えるRealmも人気です。

最近はXcodeやiTunes Connectからアプリのクラッシュ情報が見やすくなっていますので、起動時のクラッシュが頻発している場合は、こういったバックアップ処理がネックになっているかもしれません。