2

我目前在 App Store 中有一个使用 Core Data 的应用程序:该应用程序允许人们记录他们的水上和航行活动(将其想象为水手的 Strava)。我已经 3 年没有更新该应用程序了,该应用程序似乎在最新的 iOS 版本上仍然可以正常运行,但我最近计划改进该应用程序。

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

当我使用可用应用程序生成的 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 更名为 Sailor
  • SKPRTrackMO 重命名为 Activity
  • 船员 <<--->> 跟踪更名的水手 <<--->> 活动

以下是迁移问题起源实体的先前和更新数据模型的一些屏幕截图,以及一些关于我的核心数据堆栈初始化和控制台错误的代码。

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

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

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
}
4

0 回答 0