coredata entities from public configuration are not synchronized to cloudkit

In Core data public configuration, added new attribute to entities, new entities, but the changes are neither synchronized nor data is transferred to existing container schema in cloudkit.

private var _publicPersistentStore: NSPersistentStore?
var publicPersistentStore: NSPersistentStore {
    return _publicPersistentStore!
}
private var _privatePersistentStore: NSPersistentStore?
var privatePersistentStore: NSPersistentStore {
    return _privatePersistentStore!
}

private var _sharedPersistentStore: NSPersistentStore?
var sharedPersistentStore: NSPersistentStore {
    return _sharedPersistentStore!
}

static let shared = PersistenceController()

static var preview: PersistenceController = {
    let result = PersistenceController(inMemory: true)
    let viewContext = result.container.viewContext

    do {
        try viewContext.save()
    } catch {
        // Replace this implementation with code to handle the error appropriately.
        // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        let nsError = error as NSError
        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
    }
    return result
}()

let container: NSPersistentCloudKitContainer

init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: “GS”)
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
    }

    guard let defaultDescription = container.persistentStoreDescriptions.first else {
       fatalError("###\(#function): failed to retrieve a persistent store description.")
    }
    let containerIdentifier = defaultDescription.cloudKitContainerOptions!.containerIdentifier
    print(containerIdentifier)
    
    print(defaultDescription.url as Any)
    let url = defaultDescription.url?.deletingLastPathComponent()
    print(url as Any)
    
    // Public
    let publicDescription = NSPersistentStoreDescription(url: url!.appendingPathComponent("public.sqlite"))
    publicDescription.configuration = "Public"
    print(publicDescription.url)
    let publicOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: containerIdentifier)
    publicOptions.databaseScope = .public
    publicDescription.cloudKitContainerOptions = publicOptions
    
    publicDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    publicDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    
    // Private
    let privateDescription = NSPersistentStoreDescription(url: url!.appendingPathComponent("private.sqlite"))
    privateDescription.configuration = "Private"
    print(privateDescription.url)
    let privateOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: containerIdentifier)
    privateOptions.databaseScope = .private
    privateDescription.cloudKitContainerOptions = privateOptions
    
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    
    // Shared
    guard let sharedDescription = privateDescription.copy() as? NSPersistentStoreDescription else {
        fatalError("#\(#function): Copying the private store description returned an unexpected value.")
    }
    sharedDescription.url = url!.appendingPathComponent("shared.sqlite")
    print(sharedDescription.url)
    sharedDescription.configuration = "Shared"
    
    let sharedOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: containerIdentifier)
    sharedOptions.databaseScope = .shared
    sharedDescription.cloudKitContainerOptions = sharedOptions
    
    sharedDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    sharedDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
   

    container.persistentStoreDescriptions = [publicDescription, privateDescription, sharedDescription]
    

    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
        else {

            if let cloudKitContainerOptions = storeDescription.cloudKitContainerOptions {
                if #available(iOS 16.0, *) {
                    
                    if .public == storeDescription.cloudKitContainerOptions?.databaseScope {
                        print("loaded public store")
                         // self._publicPersistentStore = container.persistentStoreCoordinator.persistentStore(for: storeDescription.url!)
                    } else if .private == storeDescription.cloudKitContainerOptions?.databaseScope {
                        print("loaded private store")
                       //self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: storeDescription.url!)
                    } else if .shared == storeDescription.cloudKitContainerOptions?.databaseScope {
                        print("loaded shared store")
                        //self._sharedPersistentStore = container.persistentStoreCoordinator.persistentStore(for: storeDescription.url!)

                    }
                } else {
                    // Fallback on earlier versions
                }
            }
        }
    })
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy // external changes trumping in-memory changes.
}
func save() {
    let context = container.viewContext

    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Show some error here
            print("save error")
        }
    }
}
}

Tried new container on cloudkit, problem persists. Working previously until I updated Xcode to 15.2 and iOs 16.2. Can you please tell me why coredata is not synchronized for public configuration.

  • The above code works if the coredata entity is in private configuration, synchronization to cloud kit and data transfer works correctly. The only problem is that it does not synchronize and transfer data from public coredata configured entities to cloudkit. At a loss to understand why

  • A core data entity in the same configuration got synchronized with cloudKit after a delay of one day. Is there a wait time for synchronization?

Add a Comment