1

Core Data を使用して情報を永続化するアプリケーションがあります。同じデータにアクセスする必要がある共有拡張機能をアプリケーションに追加するため、永続ストアをアプリのサンドボックスからアプリ グループ サンドボックスに移動する必要があります。Update Core Data store location to support App Groupsで推奨されているように、移行を使用してそれを実行しています。問題は、移行中に多対多の関係が失われることです。

コア データを使用した基本的なシングル ビュー アプリケーションから始めて、問題を再現することができました。ボタンは、デフォルトの managedObjectContext (キューを追加する必要がありました) にオブジェクトを作成し、ステータス メッセージを表示するように配線されています。

AppDelegate * delegate = [UIApplication sharedApplication].delegate;

[delegate.managedObjectContext performBlock:^{
    Book * book1 = [[Book alloc] initWithEntity:[NSEntityDescription entityForName:@"Book" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];

    Book * book2 = [[Book alloc] initWithEntity:[NSEntityDescription entityForName:@"Book" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];

    Topic * topic1 = [[Topic alloc] initWithEntity:[NSEntityDescription entityForName:@"Topic" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];

    Topic * topic2 = [[Topic alloc] initWithEntity:[NSEntityDescription entityForName:@"Topic" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];

    Topic * topic3 = [[Topic alloc] initWithEntity:[NSEntityDescription entityForName:@"Topic" inManagedObjectContext:delegate.managedObjectContext] insertIntoManagedObjectContext:delegate.managedObjectContext];

    book1.title = @"Breadbaker's Apprentice";
    book1.authorName = @"Peter Reinhart";

    book2.title = @"Tartine Bread";
    book2.authorName = @"Chad Robertson";

    topic1.topicName = @"Bread";
    topic1.topicPriority = [NSDecimalNumber decimalNumberWithString:@"0.9"];
    [topic1 addBooksObject:book2];

    topic2.topicName = @"Baking";
    topic2.topicPriority = [NSDecimalNumber decimalNumberWithString:@"0.7"];
    [topic2 addBooksObject:book1];
    [topic2 addBooksObject:book2];

    topic3.topicName = @"San Francisco";
    topic3.topicPriority = [NSDecimalNumber decimalNumberWithString:@"0.2"];
    [topic3 addBooksObject:book2];

    NSError * saveError;
    if(![delegate.managedObjectContext save:&saveError])
    {
        NSLog(@"Failed to save for some reason: %@", saveError.debugDescription);
        dispatch_async(dispatch_get_main_queue(), ^{
            self.statusLabel.text = [NSString stringWithFormat:@"Failed to save for some reason: %@", saveError.debugDescription];
        });
    }
    else
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.statusLabel.text = @"OK, added objects";
        });
    }

}];

シミュレーターで実行すると、コマンド ラインで sqlite3 を使用して、これらのオブジェクトを追加した後、SQLite データベース (具体的には Core Data が作成する Z_1TOPICS リンク テーブル) を検査できます。

sqlite> .tables
ZBOOKS        ZTOPICS       Z_1TOPICS     Z_METADATA    Z_PRIMARYKEY
sqlite> SELECT * from Z_1TOPICS;
1|3
1|2
2|2
2|3
2|1

すべてが正しいように見えます。次に、2 つ目のボタンを設定して、永続ストアをアプリ グループ ディレクトリに移行します。

AppDelegate * delegate = [UIApplication sharedApplication].delegate;

NSURL *newStoreURL = [[delegate groupDocumentsDirectory] URLByAppendingPathComponent:@"Migration_Bug_Demonstration.sqlite"];

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Migration_Bug_Demonstration" withExtension:@"momd"];

NSManagedObjectModel * managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

NSPersistentStoreCoordinator *tempCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel];

NSURL *oldStoreURL = [[delegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"Migration_Bug_Demonstration.sqlite"];

NSPersistentStore   *sourceStore        = nil;
NSPersistentStore   *destinationStore   = nil;
NSDictionary *RWoptions = @{NSMigratePersistentStoresAutomaticallyOption: @YES,
                            NSInferMappingModelAutomaticallyOption: @YES};
NSDictionary * ROoptions = @{NSReadOnlyPersistentStoreOption:@YES,NSMigratePersistentStoresAutomaticallyOption: @YES,
                             NSInferMappingModelAutomaticallyOption: @YES};
NSError * error;
// Add the source store
if (![tempCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldStoreURL options:ROoptions error:&error]){
    // Handle the error
    NSLog(@"Error adding old store: %@ -- %@", error, error.userInfo);
}
else
{
    sourceStore = [tempCoordinator persistentStoreForURL:oldStoreURL];
    if (sourceStore != nil){
        // Perform the migration
        destinationStore = [tempCoordinator migratePersistentStore:sourceStore toURL:newStoreURL options:RWoptions withType:NSSQLiteStoreType error:&error];
        if (destinationStore == nil){
            NSLog(@"Error migrating store: %@ -- %@", error, error.userInfo);
            // Handle the migration error
            dispatch_async(dispatch_get_main_queue(), ^{
                self.statusLabel.text = [NSString stringWithFormat:@"Failed to migrate: %@", error.debugDescription];
            });
        } else {

            dispatch_async(dispatch_get_main_queue(), ^{
                self.statusLabel.text = @"OK, moved store";
            });
        }
    }
}

そのコードの多くは、上記のリンクされた質問からそのままです。ブックとトピックの間の関係は移行されませんが、オブジェクト自体は次のようになります。

sqlite> .tables
ZBOOKS        ZTOPICS       Z_1TOPICS     Z_METADATA    Z_PRIMARYKEY
sqlite> SELECT * FROM Z_1TOPICS;
sqlite> SELECT * FROM ZTOPICS;
1|2|1|0.2|San Francisco
2|2|1|0.7|Baking
3|2|1|0.9|Bread
sqlite> SELECT * FROM ZBOOKS;
1|1|1|Peter Reinhart|Breadbaker's Apprentice
2|1|1|Chad Robertson|Tartine Bread

実際、これらすべてを実行する前に「-com.apple.CoreData.SQLDebug 1」起動引数を使用すると、Core Data が ZTOPICS および ZBOOKS テーブルに書き込みを行っていることを確認できますが、Z_1TOPICS テーブルには書き込みを行っていません。

だから今私は立ち往生しています。この問題を調査するために他に何ができるかさえわかりません。カスタム移行を実行して、関係の移行を監視 (または手動で実行) することはできますか? 他に何ができるかわからないので、永続ストア ファイルを手動で移動しようとするかもしれません (それは No-No ですが)。御時間ありがとうございます。

4

0 に答える 0