CoreData 轻量级迁移崩溃,即使在添加映射模型后也是如此
CoreData lightweight migration crashes, even after adding a mapping model
在我的 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
有趣的是,它只显示了这两个实体的错误,但我还有更多。
经过一番搜索后
我发现我需要添加一个映射模型来在新旧版本之间迁移。所以我在 Xcode 中通过 Cmd-N 添加了它并选择了源和目标模型。
但我仍然收到错误。
shouldMigrateStoreAutomatically
和shouldInferMappingModelAutomatically
都设置为true
。
我在这里错过了什么?
旧模型在当前应用中写成Objective-C,新模型在新版本应用中写成Swift,现在也用CloudKit
。使用 Xcode 12.2.
如果需要,我很乐意添加更多信息,只是不知道什么与问题相关。
简而言之,即使使用映射模型,自动轻量级迁移也无法进行此更改。您需要进行完全手动迁移才能进行此更改。如果你查看 Apple 的 lightweight migration documentation,它说
...if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination.
这就是您想要做的,但它不会自动发生。
为什么 的较长答案详细介绍了 Core Data 的工作原理。 Xcode 没有很好地使这一点变得明显。
- 当您有两个或多个没有公共父实体的实体时,Core Data 将它们视为完全独立的。你的 SQLite 有一个
Book
table,一个 Author
table,等等。
- 当您有两个或多个实体 且 有一个共同的父实体时,Core Data 将它们视为相同 table 的特例。你的 SQLite 有一个
IDManagedObject
table。核心数据使用其他逻辑来决定 table 中的条目是 Book
还是 Author
或其他东西。
正因为如此,您实际上正在做的是将多个实体合并为一个新实体。 Core Data 不知道如何自动执行此操作,这就是它在该错误消息中告诉您的内容。
Core Data 只是抱怨这两个 table,因为它们是它首先看到的。它无法处理其中任何一个的合并,它只提到了两个 table,因为它在查看其余部分之前就放弃了。
要进行此更改,您需要创建一个迁移管理器并编写代码来执行迁移。 Apple 在 Customizing the Migration Process 中对此进行了描述。或者,根据您的具体需要,可能还有其他不需要添加新父实体的解决方案。
在我的 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
有趣的是,它只显示了这两个实体的错误,但我还有更多。
经过一番搜索后 我发现我需要添加一个映射模型来在新旧版本之间迁移。所以我在 Xcode 中通过 Cmd-N 添加了它并选择了源和目标模型。
但我仍然收到错误。
shouldMigrateStoreAutomatically
和shouldInferMappingModelAutomatically
都设置为true
。
我在这里错过了什么?
旧模型在当前应用中写成Objective-C,新模型在新版本应用中写成Swift,现在也用CloudKit
。使用 Xcode 12.2.
如果需要,我很乐意添加更多信息,只是不知道什么与问题相关。
简而言之,即使使用映射模型,自动轻量级迁移也无法进行此更改。您需要进行完全手动迁移才能进行此更改。如果你查看 Apple 的 lightweight migration documentation,它说
...if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination.
这就是您想要做的,但它不会自动发生。
为什么 的较长答案详细介绍了 Core Data 的工作原理。 Xcode 没有很好地使这一点变得明显。
- 当您有两个或多个没有公共父实体的实体时,Core Data 将它们视为完全独立的。你的 SQLite 有一个
Book
table,一个Author
table,等等。 - 当您有两个或多个实体 且 有一个共同的父实体时,Core Data 将它们视为相同 table 的特例。你的 SQLite 有一个
IDManagedObject
table。核心数据使用其他逻辑来决定 table 中的条目是Book
还是Author
或其他东西。
正因为如此,您实际上正在做的是将多个实体合并为一个新实体。 Core Data 不知道如何自动执行此操作,这就是它在该错误消息中告诉您的内容。
Core Data 只是抱怨这两个 table,因为它们是它首先看到的。它无法处理其中任何一个的合并,它只提到了两个 table,因为它在查看其余部分之前就放弃了。
要进行此更改,您需要创建一个迁移管理器并编写代码来执行迁移。 Apple 在 Customizing the Migration Process 中对此进行了描述。或者,根据您的具体需要,可能还有其他不需要添加新父实体的解决方案。