私は現在、App Store で Core Data を使用したアプリを持っています。このアプリを使用すると、人々は水やセーリングのアクティビティを記録できます (セーラー向けの Strava のようなものだと考えてください)。私は 3 年間アプリを更新していません。アプリは最新の iOS バージョンで問題なく動作しているようですが、最近アプリを改善する計画を立てました。
現在、このアプリの更新に取り組んでおり、データ モデルとスキーマを変更する必要があります。自動軽量移行を希望します。一部のエンティティ、プロパティ、および関係の名前を変更しましたが、エディターの名前変更 ID フィールドに以前の ID を入力したことを確認しました。CloudKit で更新されたスキーマを同期する機会を利用したいと考えています。Apple Developer documentation の指示に従って、同期をセットアップしました。また、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 開発コンテナーをリセットしても発生します。これがいつ表示されるかについては、明確な考えがありません (データを更新した後、または Core Data モデルを更新した後、ランダムに見えます)。アプリがクラッシュする理由はわかりますか? エンティティと関係の新しい命名を可能な限り維持したいと考えています。
- SKPRCrewMemberMOがセーラーに改名
- SKPRTrackMO の名前が Activity に変更されました
- crewMembers <<--->> は、名前が変更された船員 <<--->> のアクティビティを追跡します
以下は、移行の問題が発生したエンティティの以前のデータ モデルと更新されたデータ モデルのスクリーンショットと、Core Data スタックの初期化と取得したコンソール エラーに関するコードです。
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
}