iOS でデータを永続化する方法
iOS データ設計入門の続きです。前回は iOS であつかうデータ全般について書きましたが今回はデータをフラッシュドライブに保存する方法について説明します。
データの永続化って何?
メモリにあるデータはアプリを終了すると消えてしまいます。
アプリを終了しても残しておきたいデータはフラッシュドライブに保存する必要があります。メモリにあるフラッシュドライブに保存することをデータの永続化といいます。永続化されたデータはフラッシュドライブが壊れない限り永続的に保存され残ります。以降 iOS でフラッシュドライブがどのように管理されているのかと、データを永続化するのにどのような方法があるのかについて説明していきます。
フラッシュドライブを構成する3つの領域
データを永続化する方法を説明する前に iOS でフラッシュドライブがどのように管理されているか見ていきましょう。
iOS ではフラッシュドライブは大きくわけて以下の3つの領域に分けて管理されています*1。
- アプリ領域
アプリが自由に使うことが出来る領域。アプリごとに割り当てられていて他のアプリの領域を参照することは出来ない。 - OS 領域
OS が使用するデータが保存されている領域。OS 本体のファイルやアプリなど、基本的にアプリから参照することは出来ない。 - 共有領域
メディアライブラリ(写真、ビデオ、音楽)やイベント、連絡先など、すべてのアプリから参照することができる領域。ただしアプリから共有領域に書き込めるデータは以下の3種類に制限されている。
種類 説明 写真および動画 カメラで撮った画像データおよび動画
UIImagePickerController や AssetsLibrary を使ってデータの参照と書き込みができる連絡先 電話帳のデータ
Address Book を使ってデータの参照と書き込みができるイベント カレンダーにひもづいたイベントのデータ
Event Kit を使ってデータの参照と書き込みができる
共有データにデータを保存することも広い意味でデータの永続化になるのですが、使用頻度や用途が限定的であるため本記事では割愛します。詳細は以下を参照してください。
- Address Book Programming Guide for iOS
- About the Camera and Photo Library
- ALAssetsLibrary Class Reference
- Event Kit Programming Guide
またアプリ間でデータを共有する方法としてペーストボードを使う方法があります。ペーストボードはメモリを使ってデータを共有する方法なので本記事では割愛します。詳細は以下を参照してください。
アプリ固有領域にデータを永続化する方法
アプリ固有領域にデータを永続化する主な方法は以下の通りです。
- オブジェクトアーカイブ
オブジェクトをバイナリ形式に変換してからファイルに永続化する。一般的にはオブジェクトシリアライズと呼ばれる。使用頻度は少ないが SDK の中で頻繁に使われている。データ永続化の中で一番基礎的な技術。 - プロパティリスト
プロパティリストと呼ばれる方式でデータを永続化する
Property List Editor を使って簡単にデータの編集ができるのが特徴 - NSUserDefaults
アプリ固有の設定値を永続化することに特化したライブラリ。使用頻度は一番高い - Core Data
Core Data と言われる O/R マッピングフレームワークを使用してデータを永続化する方法
難易度が高いが使いこなせるようになると条件指定をしてデータを取得したりデータの一意性保証や Undo Redo などができるようになる。データは SQLite に保存される。
各永続化方法には、データの種類によって保存に向いている場合と向いていない場合があります。それを表にまとめると以下のようになります。
定数データ | アプリの設定値 | モデルオブジェクト | |
---|---|---|---|
アーカイブ | × | × | △(データ量少) |
プロパティリスト | ○ | △(ユーザが変更しないもの) | × |
NSUserDefaults | × | ○(ユーザが変更するもの) | × |
Core Data | × | × | ○(データ量多) |
※○…向いている △…特定条件のみ向いている ×…向いていない
iOS ではデータを保存できる場所が決められている
NSUserDefaults と Core Data はプログラマがデータの保存場所を意識する必要がありませんがオブジェクトアーカイビングとプロパティリストはプログラマがデータの保存場所を自分で管理する必要があります。
iOS でファイルを保存できる場所はセキュリティの関係上、各アプリのホームディレクトリ(/Applications/
ホームディレクトリは NSHomeDirectory() 関数で取得することができます。
NSLog(@"%@", NSHomeDirectory());
出力結果はこんな感じです。
/var/mobile/Applications/A11CE300-5F63-4918-B46C-2DFA6E18E0B7
A11 に続く文字列が GUID です。GUID はアプリによって変わります。
また iOS ではホームディレクトリ以下に専用のディレクトリがありそれぞれ役割が決まっています。
- /アプリ名.app
メインバンドルと呼ばれている。アプリのリソースファイルを保存するためのディレクトリ。読み取り専用。 - /Documents
アプリがファイルを作成して保存することができるディレクトリ。永続化したデータを格納する場合ここを使うのが一般的 - /Library/Caches
アプリが一時的に使う情報を保存するディレクトリ - /Library/Preferences
アプリケーションの設定を保存するディレクトリ。NSUserDefaults のデータが保存される - /tmp
一時ファイルを保存するディレクトリ。アプリが動作してないときに消される可能性がある
各ディレクトリのパスの取得方法は以下になります。
// アプリ名.app NSLog(@"%@", [[NSBundle mainBundle] bundlePath]); // Documents 第2引数と第3引数は固定 NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSLog(@"%@", paths[0]); // Library/caches 第2引数と第3引数は固定 NSArray *paths2 = NSSearchPathForDirectoriesInDomains( NSCachesDirectory, NSUserDomainMask, YES); NSLog(@"%@", paths2[0]); // tmp NSLog(@"%@", NSTemporaryDirectory());
/Library/Preferences は NSUserDefaults が使うディレクトリなのでファイルパスの取得方法はありません。ここに直接アクセスしたくなるようなことはほとんどないと思います。
iOS でアクセスできるディレクトリとそのパスの取得方法を図にまとめるとこのようになります。
iOS 5からデータの保存場所についてガイドラインが追加されました
iOS 5から「The iOS Data Store Guidelines specify」というデータの保存場所についてのガイドラインが追加されました。このガイドラインに違反しているアプリはリジェクトされるので気をつけてください。iCloud 関連の規約変更だと思います。
The iOS Data Store Guidelines specify:
1. Only documents and other data that is user-generated, or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and will be automatically backed up by iCloud.
2. Data that can be downloaded again or regenerated should be stored in the /Library/Caches directory. Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications.
3. Data that is used only temporarily should be stored in the /tmp directory. Although these files are not backed up to iCloud, remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device.
要約するとこんな感じです。
- /Documents ディレクトリにはユーザが自分の意思で保存したデータを保存すること
- /Library/Caches ディレクトリには、あとから再びダウンロードして復旧可能なデータを置くこと
- /tmp ディレクトリには一時的に使用するデータを保存すること
事例として、とあるアプリでサーバからダウンロードした設定情報を NSUserDefaults に保存していたらリジェクトされました。最終的にはサーバからダウンロードしたデータをメモリ上に保存するように修正して対応しました。
永続化方法の具体例
個々の永続化方法について別記事で説明していきます。
- オブジェクトアーカイビング
iOS でオブジェクトをシリアライズする方法 - プロパティリスト
iOS でプロパティリストを使ったデータの保存方法 - NSUserDefaults
NSUserDefaults を使ったデータの保存方法 - Core Data
サルでもわかる Core Data 入門【概念編】
参考書籍
- iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン
11章「こんにちは、お隣さん ー他のアプリとの協調」を参考にさせていただきました。 - 詳解 Objective-C 2.0 改訂版
16-03「 iOSのファイル保存場所」を参考にさせていただきました。
関連記事
*1:3つの領域と書きましたが、実際に領域が物理的に分かれているわけではなく、データの管理方法として3つにわけて管理されているという意味です