1

アプリケーションを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;
}

それは正しいと思いますか?コードは機能し、移行後にデータが削除され、新しいコピーが挿入されます。アプリケーションが起動するたびに移行を確認するのは嫌です。

4

1 に答える 1

0

古いデータをいつ削除するかを判断する方法がわかっている場合は、必要なすべてのエンティティを取得して削除するだけです。これを行う方法は次のとおりです (たとえば、すべてのManエンティティを削除する場合)。

    NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Man" inManagedObjectContext:myContext]];
[request setIncludesPropertyValues:NO]; //only fetch the managedObjectID

NSError * error = nil;
NSArray * men = [myContext executeFetchRequest:request error:&error];
//error handling goes here
for (NSManagedObject * man in men) {
  [myContext deleteObject:man];
}
NSError *saveError = nil;
[myContext save:&saveError];
//more error handling here
于 2012-06-13T19:30:57.357 に答える