Search code examples
core-datacloudkit

How to deduplicate Core Data entity records when using CloudKit?


Since unique constraint is not something available when using CloudKit and storing some entities inside NSPersistentCloudKitContainer would cause duplicated records after the data is synced across multiple devices.

Is there any existing best practice to deduplicate Core Data entity records stored on CloudKit?


I store the app's current user object in Core Data with iCloud user record ID as the unique identifier; however, after the entry got synced to other devices, multiple users appear under the User SQLite data.

    func getLocalUser() -> User? {
        /// Try to fetch the only local user
        let idMixpanel = DCMixpanel.shared.distinctId
        let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
        let userPredicate = NSPredicate(
            format: "%K = %@",
            #keyPath(User.idMixpanel),
            idMixpanel
        )

        fetchRequest.predicate = userPredicate

        let userList = try? container.viewContext.fetch(fetchRequest)

        if let user = userList?.first {
            if user.idCloudKit == nil {
                /// This method is async and the ID is not available immediately after function invocation
                setupCloudKitUserID()
            }
            return user
        }

        /// Create a new local user if no user found with local ID
        let userLocalNew = User(context: container.viewContext)

        userLocalNew.idMixpanel = DCMixpanel.shared.distinctId


        saveContext()

        return userLocalNew
    }

Solution

  • My solution is to create a mergeLocalUser method:

    private func mergeLocalUser() -> User? {
        /// (1) Fetch all users
        /// (2) Merge users if there are more than one user in the local database
        /// (3) Implement custom user properties merging logic
        /// (4) Delete all user instances and re-create a new user
            
        return newUserInstance
    }