Core data 重命名关系时核心数据和CloudKit集成问题(代码134110)

Core data 重命名关系时核心数据和CloudKit集成问题(代码134110),core-data,cloudkit,core-data-migration,nspersistentcloudkitcontainer,Core Data,Cloudkit,Core Data Migration,Nspersistentcloudkitcontainer,我目前有一个应用程序使用应用程序商店中的核心数据:该应用程序允许人们记录他们的水上活动和航海活动(可以把它想象成水手的Strava)。我已经三年没有更新这个应用了,这个应用在最新的iOS版本上似乎仍然运行良好,但我最近计划改进这个应用 我目前正在对此应用程序进行更新,需要更改数据模型和模式。我想要一个自动的轻量级迁移。我重命名了一些实体、属性和关系,但我确保将以前的ID放在编辑器的重命名ID字段中。 我想利用这个机会在CloudKit上同步更新的模式。我按照Apple开发者文档中的说明设置同步。

我目前有一个应用程序使用应用程序商店中的核心数据:该应用程序允许人们记录他们的水上活动和航海活动(可以把它想象成水手的Strava)。我已经三年没有更新这个应用了,这个应用在最新的iOS版本上似乎仍然运行良好,但我最近计划改进这个应用

我目前正在对此应用程序进行更新,需要更改数据模型和模式。我想要一个自动的轻量级迁移。我重命名了一些实体、属性和关系,但我确保将以前的ID放在编辑器的重命名ID字段中。 我想利用这个机会在CloudKit上同步更新的模式。我按照Apple开发者文档中的说明设置同步。我还确保使用InitializeLoudkitschema()初始化模式。当我访问仪表板时,我看到了正确的模式。容器仅处于开发模式,未投入生产

当我使用可用应用程序生成的sqlite文件启动应用程序时,迁移似乎运行良好,因为数据仍然存在并且正确。我可以在应用程序中正常导航,当我访问CloudKit仪表板时,数据已正确保存

但有时,应用程序在启动时崩溃,并出现以下错误:

UserInfo={reason=CloudKit integration forbids renaming 'crewMembers' to 'sailors'.
Older devices can't process the new relationships.
NSUnderlyingException=CloudKit integration forbids renaming 'crewMembers' to 'sailors'.
Older devices can't process the new relationships.}}}
Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." 
相关实体被重命名,因为关系和关系是多对多的,双方都是可选的。即使我重置了CloudKit开发容器,也会发生这种情况。我真的不清楚这是什么时候出现的(似乎是随机的,在我更新了一些数据或更新了核心数据模型之后)。知道为什么应用程序会崩溃吗?我希望尽可能保留我的实体和关系的新名称

  • SKPRCrewMemberMO更名为水手
  • SKPRTrackMO重命名为“活动”
  • 船员追踪更名水手的活动
以下是迁移问题起源处实体先前和更新的数据模型的一些屏幕截图,以及一些关于我的核心数据堆栈初始化和控制台错误的代码

附:这个应用程序被几百人使用。这并不是很多,但仍然有一些有几十个记录的活动,我不想破坏任何东西,丢失或损坏数据。我可以发布一个新的应用程序,但用户会失去他们的进度,因为它只保存在本地的一个共享容器中(使用应用程序组是因为我想与Apple Watch扩展共享核心数据)。我将失去与用户群和应用商店相关的东西

private init() {
    container = NSPersistentCloudKitContainer(name: "Skipper")
    
    guard let description = container.persistentStoreDescriptions.first else {
        fatalError("###\(#function): Failed to retrieve a persistent store description.")
    }
    description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    let id = "iCloud.com.alepennec.sandbox20201013"
    let options = NSPersistentCloudKitContainerOptions(containerIdentifier: id)
    description.cloudKitContainerOptions = options
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    
    do {
        try container.initializeCloudKitSchema()
    } catch {
        print("Unable to initialize CloudKit schema: \(error.localizedDescription)")
    }
    
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}

我的理解是,为了保持向后兼容性,CloudKit不允许重命名字段。因此,您需要创建新字段,而不是重命名旧字段。问题是——这对任何下载新版本的人来说都是好的,但是那些旧版本在字段重命名后会怎么样呢?我很惊讶它不会每次都崩溃……尽管我没有尝试过类似的迁移,所以还是有点小题大做:)我可能已经找到了崩溃的原因:当我使用以前版本(比如V1)的sqlite文件启动应用程序时,该文件被迁移到最后一个模型(比如V2)。但是,如果我在没有创建新的核心数据模型的情况下再次对模型进行更改,则无法打开更新的sqlite文件(V2)→ 我需要制作一个新版本的模型,以便V2文件可以迁移到V3。如果我在再次进行一些模型更改后使用V1文件启动应用程序,则会使用更新的模型进行迁移,因此不会遇到错误。