ios – Duplicated records with the same `objectId` in Core Data with CloudKit


I have a Swift App that uses Core Data with CloudKit. CloudKit duplicated all records in the container, across all of my devices. The duplicated records have the same objectId. My code uses NSMergeByPropertyObjectTrumpMergePolicy so I assumed CloudKit would have merged the records on Apple’s servers. What could have caused this? How can it be prevented?

Below is how I create the container.

Thank you

class DataManager: NSObject, ObservableObject {
    private var containerImpl: NSPersistentContainer? = nil
    
    var container: NSPersistentContainer {
        if containerImpl == nil {
            containerImpl = makeLazyContainer()
        }
        return containerImpl!
    }
    
    var privatePersistentStore: NSPersistentStore?
    
    private func makeLazyContainer() -> NSPersistentContainer {
        var container: NSPersistentContainer? = nil
        
        // https://stackoverflow.com/questions/58179862/cloudkit-sync-using-nspersistentcloudkitcontainer-in-ios13

        let dontSyncToiCloud = UserDefaults.standard.bool(forKey: "dontSyncToiCloud")
        var cloudContainer : NSPersistentCloudKitContainer? = nil
        if !dontSyncToiCloud {
            print("syncing to iCloud")
            cloudContainer = NSPersistentCloudKitContainer(name: "Model")
            container = cloudContainer
        } else {
            print("not syncing to iCloud")
            container = NSPersistentContainer(name: "Model")
        }
        
        let description = container!.persistentStoreDescriptions.first
        description!.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        description!.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        
        container!.loadPersistentStores(completionHandler: {
            (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            } else {
                self.privatePersistentStore = container!.persistentStoreCoordinator.persistentStore(for: storeDescription.url!)
            }
        })
        
        container!.viewContext.automaticallyMergesChangesFromParent = true
        container!.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

        if !dontSyncToiCloud {
            // Only initialize the schema when building the app with the Debug build configuration.
#if DEBUG
            do {
                // Use the container to initialize the development schema.
                // thise needs to be done after persistent store load
                print("initialize the development schema")
                try cloudContainer!.initializeCloudKitSchema(options: [])
            } catch {
                print("error: \(error.localizedDescription)")
            }
#endif
        }
        
        do {
            try container!.viewContext.setQueryGenerationFrom(.current)
        } catch {
            fatalError("###\(#function): Failed to pin viewContext to the current generation:\(error)")
        }
        
        return container!
    }
}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img