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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
<relationship name="careSchedule" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="CareScheduleMO" inverseName="plant" inverseEntity="CareScheduleMO"/>
|
||||
<relationship name="identifications" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="IdentificationMO" inverseName="plant" inverseEntity="IdentificationMO"/>
|
||||
<relationship name="plantCareInfo" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="PlantCareInfoMO" inverseName="plant" inverseEntity="PlantCareInfoMO"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="IdentificationMO" representedClassName="IdentificationMO" syncable="YES">
|
||||
<attribute name="confidenceScore" attributeType="Double" defaultValueString="0.0" usesScalarType="YES"/>
|
||||
@@ -34,11 +29,6 @@
|
||||
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarType="NO"/>
|
||||
<attribute name="source" attributeType="String"/>
|
||||
<relationship name="plant" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PlantMO" inverseName="identifications" inverseEntity="PlantMO"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="CareScheduleMO" representedClassName="CareScheduleMO" syncable="YES">
|
||||
<attribute name="fertilizerSchedule" attributeType="String"/>
|
||||
@@ -50,11 +40,6 @@
|
||||
<attribute name="wateringSchedule" attributeType="String"/>
|
||||
<relationship name="plant" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PlantMO" inverseName="careSchedule" inverseEntity="PlantMO"/>
|
||||
<relationship name="tasks" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="CareTaskMO" inverseName="careSchedule" inverseEntity="CareTaskMO"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="CareTaskMO" representedClassName="CareTaskMO" syncable="YES">
|
||||
<attribute name="completedDate" optional="YES" attributeType="Date" usesScalarType="NO"/>
|
||||
@@ -64,11 +49,6 @@
|
||||
<attribute name="scheduledDate" attributeType="Date" usesScalarType="NO"/>
|
||||
<attribute name="type" attributeType="String"/>
|
||||
<relationship name="careSchedule" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CareScheduleMO" inverseName="tasks" inverseEntity="CareScheduleMO"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PlantCareInfoMO" representedClassName="PlantCareInfoMO" syncable="YES">
|
||||
<attribute name="additionalNotes" optional="YES" attributeType="String"/>
|
||||
@@ -86,10 +66,5 @@
|
||||
<attribute name="trefleID" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarType="YES"/>
|
||||
<attribute name="wateringScheduleData" attributeType="Binary"/>
|
||||
<relationship name="plant" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PlantMO" inverseName="plantCareInfo" inverseEntity="PlantMO"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
</model>
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.icloud-container-identifiers</key>
|
||||
<array/>
|
||||
<array>
|
||||
<string>iCloud.com.t-t.PlantGuide</string>
|
||||
</array>
|
||||
<key>com.apple.developer.icloud-services</key>
|
||||
<array>
|
||||
<string>CloudKit</string>
|
||||
|
||||
Reference in New Issue
Block a user