Core Dataのマイグレーション

2010/09/13

おぉ、Core Dataでマイグレーションが使えるんだ!

参考ページ

(旧) Cocoaの日々 CoreData - マイグレーションCore Data Migration Problems?Core Dataの自動マイグレーション

確かにマイグレーションできないと管理が大変・・・と言うか、データモデルが少しでも変更されるとアプリが起動しなくなる(アプリを削除すれば起動するがデータが消える)のでマイグレーションは必須です。

とりあえず、今作成しているアプリで調査がたら試してます。

モデルバージョン

(1) xcdatamodelを開く。 (2) 設計>データモデル>モデルバージョンを追加 を選択する。 iphone

(3) xcdatamodelが追加される。 iphone

(4) 新規ファイル> ResourseからMapping Modelを選択する。 iphone

(5) ファイル名をつけて【次へ】進む。 iphone ※ファイル名はバージョンと絡めた方が、見た目はわかりやすいかも知れない

(5) ソースモデルの設定、ディスティネーションの設定を選択し【完了】する。 iphone ※ソースモデルは現在のバージョンのxcdatamodel、ディスティネーションは次のバージョンのxcdatamodel

(6) 作成したMapping Modelファイルを開く。 iphone

【差分を表示】をクリックすると、バージョンの差分が表示されている。 iphone

(7) 最新のxcdatamodelを開き、設計>データモデル>現在のバージョンを設定を選択する。 iphone

これで、モデルのバージョン移行が完了です。 ・・・と、アプリをビルドしてみると

落ちてしまいます

persistentStoreCoordinatorにoptionsを設定

CoreDataでプロジェクトを作成すると、persistentStoreCoordinator等の雛形を作成してくれる訳だけど、 なぜかマイグレーションで管理した場合は、以下のoptionsのコードを記述しないとエラーになってしまう。

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                         nil];

サンプルコード

initWithManagedObjectModelするときに、optionsを設定してやる。

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    NSLog(@"----- App persistentStoreCoordinator -----");
    if (persistentStoreCoordinator_ != nil) {
        return persistentStoreCoordinator_;
    }
    
    NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"iMusicScore.sqlite"]];
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                             nil];
    
    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_;
}

これで、モデルのバージョン移行が完了です! 勿論、旧バージョンにも戻せます。

不明点

さて、うまく動作したはいいけど、モデルのクラスファイルが更新の仕方がわからないです。 今は、手動でモデルを置き換えてます。

ここら辺は、調査しないといけないとこです。 わかったら、またトピックにする予定。