More iPhone 3 Development: Tackling iPhone SDK 3 (Beginning) Chapter 5 のまとめ。
まずはじめに、Core Dataを利用して保存したデータは、データモデルに変更があると、そのままでは使えなくなる。データモデルを変更したにも関わらず、旧構成のデータが保存されている状態では、アプリは起動すらできない。
かといって、初回リリース時に今後のすべてのアップデートまで見越したデータ構成にしておくことは難しい。そこで、データモデルのバージョン管理が必要になるのだ。
Core Dataの勉強を始めたばかりの頃、このことを知らずに結構はまったっけ。
一瞬、データモデルの変更はできないのか??と思ったりもしたけれど、そんなことはないです。困りますから・・・。
新バージョンの作成
データモデルを編集する前に必ず新しいバージョンのモデルを作成する。
該当する .xcdatamodel ファイルを選択し、メニューバーから、「設計」→「データモデル」→「モデルバージョンを追加」を選ぶ。これで、既存のデータモデルのコピーができあがる。
ファイルリストを見ると、このようにひとつバージョンが増えているのがわかる。
緑のチェックマークがついているのが現(新しい)バージョンだ。デフォルト動作では、末尾についているバージョン番号が大きくなればなるほど古いということになる。ここは要注意。
要は、毎回バックアップをとるといったイメージである。変更していくのは常に同じ名前のファイルでよい。
もちろん、必要があれば現バージョンを変更することもできるし、バージョン名を変更することも可能。
データモデルの読み込み
バージョン管理されていない(ひとつしかない)データモデルは、コンパイラにより.momファイルに変換される。一方、バージョン管理済みのデータモデルは、.momdとなる。
ManagedObjectModelのクラスメソッドmergedModelFromBundlesを使うと、バンドル内にあるモデルをすべて読み込むことができる。Xcodeのテンプレートでもこの方法を使っている(以下)。.momファイルも.momdファイルもこれで読み込み可能だが、ビルド時にクリーンをし忘れたりすると、やや面倒なことになる(可能性がある)。
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
確実にバージョンつけされている現データモデルを読み込みたければ、以下のように変更すればよい。
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"SuperDB" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}
このようにしておくと、Core Data は、バージョン付けされた.momdファイルのみを読み込み、.momは、バージョン移行に必要な場合にのみ利用される。
データモデルのバージョン移行
データモデルのバージョン移行(移植?)には二通りあるが、ここでは簡易な移行のみを使う。基本的に、attributeやentityの追加/削除は、この方法が使える。
データモデルを新しいバージョンへ移行するためには、NSPersistentStoreCoordinatorを生成するメソッドにオプションを指定すれば、あとは自動でやってくれる。
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator(だいたいAppDelegate内にある)に注目。テンプレートでは以下のようになっている。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"SuperDB.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
addPErsistentStoreWithType:configuration:URL:options:error: のoptionsに、データ移行オプションを指定する。オプションの指定にはNSDictionaryを用いる。
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
これを、上記メソッドのoptions:に渡してあげればよい。これで、データモデル変更後も、正しく動作するようになる。
Apress
売り上げランキング: 29207



