CS193p - Lecture 12

iTunes U スタンフォード大学のiOSアプリ開発講義のLecure 12(Persistence)の講義メモです。

永続性

■オブジェクトに永続性を持たせる方法

  • プロパティリスト
  • アーカイブ
  • ファイルシステム
  • SQLite(オープンソースのSQLデータベース)
  • Core Data(SQL上のオブジェクト指向データベースメカニズム)

■プロパティリスト

・NSArray or NSDictionaryに格納されているものを保存

  writeToURL:atomically:     

(atomicallyは、一旦テンポラリに作成するので中途半端に書き出されることはない)

        initWithContentsOfURL:
        dataWithContentsOfURL:
        dictionaryWithContentsOfURL:
・NSUserDefault(100k程度のデータを保存する時に使う)
・NSPropertyListSerialization(NSDataとの変換)

■オブジェクトのアーカイブ

描画オブジェクトやループしているオブジェクト(root view->subview->root view etc.)を保存して復元させることができる。
図で書かれたオブジェクトはNSCodingプロトコルが必要になる。

- (void)encodeWithCoder:(NSCoder *)coder;
- initWithCoder:(NSCoder *)coder;

保存と復元にはMSKeyd[Un]Archiverクラスを使用する。

<使用例>

id <NSCoder> object = ...;
NSData *data =

[NSKeyedArchiver archivedDataWithRootObject:object];

id <NSCoder> dup =

[NSKeyedArchiver unarchiveObjectWithData:data];

この方法では、巨大な図をまるごとロードして元通りにしないといけない。
しかも、データはアーカイブ時にディープコピーされるので、そのサイズ分丸ごとのコピーを保持することになる。

図を保存するには、Core Dataを使った方が10,000倍効率的である。

■ファイルシステム
iOSは、基本的にUnix(BSD系のMach)を元にしているので、ファイルシステムの構造はUnixと同じでルート/から始まる。しかし、ファイルシステムのプロテクションがあるので、全てのものを操作出来るわけではない。
読み書き出来るのは、サンドボックスと呼ばれる領域のみである。サンドボックスのおかげでセキュリティが確保され、アプリ削除時にアプリのデータも削除される。
※iCloudは少し違っていて、サンドボックス内に保存した時にiCloudがオンに設定されていればクラウド上に保存されるので、アプリを削除してもクラウド上に残っている。

・サンドボックスの構造

アプリは単一の大きなバイナリではなく、実際にはディレクトリで、その中に実行可能なバイナリやストーリーボードやXcodeに入れた画像ファイルなどが入っている。

このディレクトリは、readonlyで書き込みは出来ない。

使用可能なのは、サンドボックス内の次のディレクトリ。

  • Documents ディレクトリ:ユーザが作成したデータを恒久的に保存する場所
  • Caches ディレクトリ:一時的なファイルを保存する場所(バックアップされない)
  • …(その他は、NSSearchPathDirectoryをドキュメントでチェック)

・使用可能なディレクトリの取得

- (NSArray *)URLsForDirectory: (NSSearchPathDirectory)directory

inDomains:(NSSearchPathDomainMask)domainMask;

//iOSではdomainMaskは常にNSUserDomainMaskを指定する

※ このAPIはMacと共通なので汎用的に定義されているが、iOSではdomainMaskには必ずNSUserDomainMaskを指定する。

※ 戻り値はパスの配列。Macでは複数のディレクトリの可能性があるので配列になっているが、iOSでは参照出来る範囲が制限されていて1つしかないのでLastObjectで取得すれば良い。

NSSearchPathDirectoryの値:

NSDocumentsDirectory
NSCachesDirectory
NSAutosavedInformationDirectory

・NSFileManager

ファイル操作を受け持ってくれるクラス(ファイルの属性取得や削除、書き込み完了通知など)
スレッドセーフなので、1つのインスタンスを別々にスレッドで処理しない限りは、どのスレッドで処理しても大丈夫。

・NSString

パス文字列の作成

- (NSString *)stringByAppendingPathComponent:(NSString *)component;

- (NSString *)stringByDeletingLastPathComponent;

 

文字列をファイルに保存

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag

encoding:(NSStringEncoding)encoding //ASCII,ISOLatin1,etc.

error:(NSError **)error;

 

保存したファイルから読み込み

- (NSString *)stringWithContentsOfFile:(NSString *)path

usedEncoding:(NSStringEncoding *)encoding

error:(NSError **)error;

 

■SQLite

単一ファイルにSQLが入っている。
パフォーマンスが良く、メモリ消費が少なく、トランザクションベースで信頼性が高い。
ビデオやファイルシステムのディレクトリ構造やサウンドやイメージには使わない。
同時処理が可能で、異なるスレッドで同時にSQL処理も可能である。しかし、これはサーバーベースのSQLではなくファイルベースのSQLなので、100など大量の同時実行はしないこと。

・API

int sqlite3_open(constchar*filename,sqlite3**db); //データベース作成
int sqlite3_exec(sqlite3 *db,     //SQLコマンドの実行
                 const char *sql,
                 int (*callback)(void *, int, char **, char **),
                 void *context,
                 char **error);
int mycallback(void*context,intcount,char**values,char**cols);
int sqlite3_close(sqlite3 *db);   //データベースクローズ