From d125216a95490edfead890952fe3fddbfc78264d Mon Sep 17 00:00:00 2001 From: Trey t Date: Fri, 23 Jan 2026 14:21:52 -0600 Subject: [PATCH] Add CloudKit sync for cross-device data persistence - Switch CoreDataStack from NSPersistentContainer to NSPersistentCloudKitContainer - Configure CloudKit container: iCloud.com.t-t.PlantGuide - Remove uniqueness constraints from all Core Data entities (CloudKit incompatible) - Add CloudKit container identifier to entitlements Co-Authored-By: Claude Opus 4.5 --- .../Local/CoreData/CoreDataStack.swift | 12 ++++++--- .../PlantGuideModel.xcdatamodel/contents | 25 ------------------- PlantGuide/PlantGuide.entitlements | 4 ++- 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/PlantGuide/Data/DataSources/Local/CoreData/CoreDataStack.swift b/PlantGuide/Data/DataSources/Local/CoreData/CoreDataStack.swift index 31af006..f8b79ae 100644 --- a/PlantGuide/Data/DataSources/Local/CoreData/CoreDataStack.swift +++ b/PlantGuide/Data/DataSources/Local/CoreData/CoreDataStack.swift @@ -6,6 +6,7 @@ // for plant identification iOS app. // +import CloudKit import CoreData import Foundation @@ -105,7 +106,7 @@ final class CoreDataStack: CoreDataStackProtocol, @unchecked Sendable { // - The coreDataQueue serializes any direct container operations /// The persistent container managing the Core Data stack - private let persistentContainer: NSPersistentContainer + private let persistentContainer: NSPersistentCloudKitContainer /// Serial queue for thread-safe operations private let coreDataQueue = DispatchQueue(label: "com.plantguide.coredata", qos: .userInitiated) @@ -142,8 +143,8 @@ final class CoreDataStack: CoreDataStackProtocol, @unchecked Sendable { private static func createPersistentContainer( modelName: String, migrationConfig: MigrationConfiguration - ) -> NSPersistentContainer { - let container = NSPersistentContainer(name: modelName) + ) -> NSPersistentCloudKitContainer { + let container = NSPersistentCloudKitContainer(name: modelName) // Configure store description with migration options let storeDescription = container.persistentStoreDescriptions.first @@ -154,6 +155,11 @@ final class CoreDataStack: CoreDataStackProtocol, @unchecked Sendable { storeDescription?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) storeDescription?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) + // Configure CloudKit container + storeDescription?.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions( + containerIdentifier: "iCloud.com.t-t.PlantGuide" + ) + container.loadPersistentStores { storeDescription, error in if let error = error as NSError? { // Log the error - in production, consider recovery strategies diff --git a/PlantGuide/Data/DataSources/Local/CoreData/PlantGuideModel.xcdatamodeld/PlantGuideModel.xcdatamodel/contents b/PlantGuide/Data/DataSources/Local/CoreData/PlantGuideModel.xcdatamodeld/PlantGuideModel.xcdatamodel/contents index 611bf72..f9058ee 100644 --- a/PlantGuide/Data/DataSources/Local/CoreData/PlantGuideModel.xcdatamodeld/PlantGuideModel.xcdatamodel/contents +++ b/PlantGuide/Data/DataSources/Local/CoreData/PlantGuideModel.xcdatamodeld/PlantGuideModel.xcdatamodel/contents @@ -19,11 +19,6 @@ - - - - - @@ -34,11 +29,6 @@ - - - - - @@ -50,11 +40,6 @@ - - - - - @@ -64,11 +49,6 @@ - - - - - @@ -86,10 +66,5 @@ - - - - - diff --git a/PlantGuide/PlantGuide.entitlements b/PlantGuide/PlantGuide.entitlements index 9e0940e..bac9011 100644 --- a/PlantGuide/PlantGuide.entitlements +++ b/PlantGuide/PlantGuide.entitlements @@ -5,7 +5,9 @@ aps-environment development com.apple.developer.icloud-container-identifiers - + + iCloud.com.t-t.PlantGuide + com.apple.developer.icloud-services CloudKit