В моей модели CoreData я создал абстрактную сущность (IDManagedObject
), чтобы использовать общий атрибут для других моих сущностей.
Когда я впервые запустил его, я получил несколько ошибок Cannot merge multiple root entity source tables into one destination entity root table
.
Полная ошибка выглядит следующим образом:
Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." UserInfo = {sourceURL=file:///Users/koen/Library/Developer/CoreSimulator/Devices/8E2C0F01-ABF3-4414-A01A-EE4FFEF8D187/data/Containers/Data/Application/B7A9A4EE-EB57-434F-B1A9-576DCD80CFBD/Library/Application%20Support/MyApp.sqlite, reason=Cannot migrate store in-place: Cannot merge multiple root entity source tables into one destination entity root table, destinationURL=file:///Users/koen/Library/Developer/CoreSimulator/Devices/8E2C0F01-ABF3-4414-A01A-EE4FFEF8D187/data/Containers/Data/Application/B7A9A4EE-EB57-434F-B1A9-576DCD80CFBD/Library/Application%20Support/MyApp.sqlite, NSUnderlyingError=0x6000019fb810 {Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." UserInfo = {message=Cannot merge multiple root entity source tables into one destination entity root table, destinationRootEntity=IDManagedObject, NSUnderlyingException=Cannot merge multiple root entity source tables into one destination entity root table, sourceRootEntities=(
Book,
Author
), reason=Cannot merge multiple root entity source tables into one destination entity root table}}}, ["NSUnderlyingError": Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." UserInfo = {message=Cannot merge multiple root entity source tables into one destination entity root table, destinationRootEntity=IDManagedObject, NSUnderlyingException=Cannot merge multiple root entity source tables into one destination entity root table, sourceRootEntities=(
Book,
Author
), reason=Cannot merge multiple root entity source tables into one destination entity root table}, "destinationURL": file:///Users/koen/Library/Developer/CoreSimulator/Devices/8E2C0F01-ABF3-4414-A01A-EE4FFEF8D187/data/Containers/Data/Application/B7A9A4EE-EB57-434F-B1A9-576DCD80CFBD/Library/Application%20Support/MyApp.sqlite, "sourceURL": file:///Users/koen/Library/Developer/CoreSimulator/Devices/8E2C0F01-ABF3-4414-A01A-EE4FFEF8D187/data/Containers/Data/Application/B7A9A4EE-EB57-434F-B1A9-576DCD80CFBD/Library/Application%20Support/MyApp.sqlite, "reason": Cannot migrate store in-place: Cannot merge multiple root entity source tables into one destination entity root table]: file MyApp/SceneDelegate.swift, line 96
Интересно, что он показывает ошибку только для этих двух сущностей, но у меня их гораздо больше.
После небольшого поиска Я обнаружил, что мне нужно добавить модель сопоставления для перехода между старой и новой версией. Поэтому я добавил это через Cmd-N в Xcode и выбрал исходную и конечную модели.
Но я все еще получаю сообщение об ошибке.
И shouldMigrateStoreAutomatically
, и shouldInferMappingModelAutomatically
установлены на true
.
Что мне здесь не хватает?
Старая модель находится в текущем приложении, написанном на Objective-C, новая модель находится в новой версии приложения, написанного на Swift, и теперь также использует CloudKit
. Использование Xcode 12.2.
Я рад добавить дополнительную информацию, если это необходимо, просто не знаю, что будет иметь отношение к вопросу.
Короткая версия заключается в том, что автоматическая упрощенная миграция не может внести это изменение даже с моделью сопоставления. Чтобы внести это изменение, вам необходимо выполнить полную ручную миграцию. Если вы посмотрите документацию Apple облегченной миграции, там сказано, что
...если два существующих объекта не имеют общего родителя в источнике, они не могут иметь общего родителя в месте назначения.
Это то, что вы пытаетесь сделать, но это не может произойти автоматически.
Более длинный ответ на вопрос «почему» содержит некоторые детали того, как работают Core Data. Xcode не очень хорошо делает это очевидным.
Book
, таблица Author
и так далее.IDManagedObject
. Core Data использует другую логику, чтобы решить, является ли запись в этой таблице Book
, Author
или чем-то еще.Из-за этого то, что вы на самом деле делаете, — это объединение нескольких объектов в один новый объект. Core Data не знает, как сделать это автоматически, о чем сообщает сообщение об ошибке.
Core Data жалуется только на эти две таблицы, потому что они появляются первыми. Он не может справиться с объединением ни одной из них и упоминает только две таблицы, потому что сдается, не взглянув на остальные.
Чтобы внести это изменение, вам потребуется создать диспетчер миграции и написать код для выполнения миграции. Apple описывает это в разделе Настройка процесса миграции. Или, в зависимости от того, что именно вам нужно, могут быть другие решения, не требующие добавления нового родительского объекта.
Если это для доступа к значениям после выборки, возможно, объявите протокол с общим атрибутом и согласуйте с ним ваши классы Core Data. Затем используйте протокол для обработки их как одного типа.
Кстати, эта ссылка от 2012 года, и, что удивительно, я не могу найти ничего более свежего и использующего Swift о моделях отображения. Более того, на следующей странице написано: «Если вы используете iCloud, вы можете перенести содержимое магазина только с помощью автоматической упрощенной миграции». Правильно ли я понимаю, что, поскольку я использую CloudKit, пользовательская миграция вообще не будет работать?
Если он не обновлялся с 2012 года, значит, он не обновлялся с тех пор, как не существовало Cloud! Я не знаю, какая там ситуация. С точки зрения языка, хотя он и использует Objective-C, структура, классы и функции одинаковы.
Спасибо что подметил это. Должно быть, пропустил вашу первую цитату при исследовании этого. Единственная причина, по которой я это делаю, заключается в том, чтобы упростить доступ/извлечение общего атрибута. Поэтому вместо того, чтобы получать
Author
,Book
и т. д., я могу просто получить доступ кIDManagedObject
.