アプリケーションをv1からv2にアップグレードする際に、コアデータモデルにいくつかの小さな変更を加えました。変更は、モデルに新しい属性を追加するだけです。
変更前と変更後のデータモデルをバージョン管理し、アプリデリゲートに次のコードを実装しました。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ISDEmployees.sqlite"];
NSLog(@"storeURL:%@",storeURL);
NSError *error = nil;
// Create a dictionary for automatic lightweight core data migration
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
// Set up the persistent store and migrate if needed
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
基本的に、移行オプションが追加された標準のpersistentStoreCoordinatorです。このコードはうまく機能し、私のデータベースは正常に更新されています。私が抱えている問題は、データベースの更新後に、データベース内のすべてのデータを更新して、新しい列にデータが入力されるようにする必要があることです。関連するエンティティ/テーブルからデータを削除し、列/属性が追加された新しいデータセットをアプリケーションに再ダウンロードするように強制することを考えていました。
削除/更新を実行する方法/場所がわかりません。一般的なアプリケーションフローは次のとおりです。
- WebAPIに対する検証を使用してログインします
- ログインに成功したら、APIを呼び出して、最新の追加/更新されたレコードを取得します。
- 更新されたデータを表示する
このコードをpersistentStoreCoordinatorに追加することで、移行が必要かどうかを確認できます。
// Get the current data store meta data
BOOL migrationNeeded = NO;
NSDictionary *existingStoreData = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL error:&error];
if (existingStoreData)
{
// Check to see if new model is not the same as the existing mode, meaning a migration is required
if (![self.managedObjectModel isConfiguration:nil compatibleWithStoreMetadata:existingStoreData])
{
migrationNeeded = YES;
}
}
どんな助けでも大歓迎です!!
アップデート#1:
以下のフィードバックに基づいて、次の変更を行いました。
AppDelegateのmigrationNeededをローカルクラス変数からパブリッククラス変数に変更しました。ログインビューに、次のメソッドを追加しました。
- (void)checkForDatabaseMigration
{
// Get a copy of the managed object context. If a migration is needed, it will kick it off
NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
if ([(AppDelegate *)[[UIApplication sharedApplication] delegate] migrationNeeded])
{
// Delete all data from the table
}
managedObjectContext = nil;
}
それは正しいと思いますか?コードは機能し、移行後にデータが削除され、新しいコピーが挿入されます。アプリケーションが起動するたびに移行を確認するのは嫌です。