首页 > 解决方案 > CoreData 轻量级迁移崩溃,即使添加了映射模型

问题描述

在我的 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 添加它并选择源和目标模型。

但我仍然收到错误消息。

两者shouldMigrateStoreAutomaticallyshouldInferMappingModelAutomatically都设置为true

我在这里想念什么?

旧模型在当前用 Objective-C 编写的应用程序中,新模型在用 Swift 编写的应用程序的新版本中,现在也使用CloudKit. 使用 Xcode 12.2。

如果需要,我很乐意添加更多信息,只是不知道与该问题相关的内容。

标签: ioscore-datacloudkitmapping-model

解决方案


简短的版本是,即使使用映射模型,自动轻量级迁移也无法进行此更改。您需要进行完全手动迁移才能进行此更改。如果您查看 Apple 的轻量级迁移文档,它会说

...如果两个现有实体在源中不共享一个共同的父级,则它们不能在目标中共享一个共同的父级。

这是你想要做的,但它不能自动发生。

更长的答案为什么会涉及 Core Data 如何工作的一些细节。Xcode 并没有很好地说明这一点。

  • 当您有两个或多个实体而没有共同的父实体时,Core Data 将它们视为完全独立的。你的 SQLite 有一个Book表,一个Author表,等等。
  • 当您有两个或多个实体具有共同的父级时,Core Data 将它们视为同一个表的特殊情况。你的 SQLite 有一个IDManagedObject表。Core Data 使用其他逻辑来决定该表中的条目是 aBook还是 anAuthor或其他东西。

因此,您实际上正在做的是将多个实体合并到一个新实体中。Core Data 不知道如何自动执行此操作,这就是它在该错误消息中告诉您的内容。

Core Data 只是抱怨这两个表,因为它们是它看到的第一个表。它无法处理合并它们中的任何一个,它只提到了两个表,因为它在查看其余表之前就放弃了。

要进行此更改,您需要创建一个迁移管理器并编写代码来进行迁移。Apple 在自定义迁移过程中对此进行了描述。或者,根据您的具体需要,可能还有其他解决方案不需要添加新的父实体。


推荐阅读