Почему отношения "многие ко многим" исчезают при перемещении основного хранилища данных?
У меня есть приложение, которое использует Core Data для сохранения информации. Я добавляю расширение Share в свое приложение, которому потребуется доступ к тем же данным, поэтому мне нужно переместить мое постоянное хранилище из изолированной программной среды моего приложения в изолированную программную среду группы приложений. Как рекомендовано в разделе "Обновление хранилища основных данных для поддержки групп приложений", для этого я использую миграцию. Проблема в том, что мои отношения многие ко многим исчезают во время этой миграции.
Мне удалось воссоздать проблему, начав с базового приложения Single View с базовыми данными. Кнопка подключена, чтобы создать объекты в defaultObjectContext по умолчанию (к которому мне пришлось добавить очередь), и показать сообщение о состоянии:
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 и, в частности, таблицы ссылок Z_1TOPICS, которую создает Core Data, после добавления этих объектов:
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
Все выглядит правильно. Затем настраивается вторая кнопка для переноса постоянного хранилища в каталог группы приложений:
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.
Так что теперь я застрял. Я даже не уверен, что еще я могу сделать, чтобы исследовать эту проблему - может быть, выполнить пользовательскую миграцию, чтобы я мог наблюдать (или даже вручную выполнять) миграцию отношений? Я мог бы просто попытаться переместить файлы постоянного хранилища вручную (даже если это Нет-Нет), потому что я не уверен, что еще я могу сделать. Спасибо за ваше время.