core-dataswiftuicloudkitnspersistentcloudkitcontainer

Problem getting NSPersistentCloudKitContainer to sync between devices (SwiftUI, iOS)


I have set up my Core Data model with NSPersistentCloudKitContainer:

struct PersistenceController {
    static let shared = PersistenceController()
    let container: NSPersistentCloudKitContainer
    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "LearningCloudKit")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
}

That's pretty much the standard stuff that Xcode presents when I create a new project with CoreData and CloudKit.

The view presenting the data is fed by

    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: false)],
        animation: .default)
    private var items: FetchedResults<Item>

Sync between my devices works somewhat but when I enter new data into one device it takes more than 15 minutes to show up on the other. Don't know, some times it doesn't arrive until I force close the app and restart. And sometimes I have to enter data on one device and force close to see data from other device.

I have enabled remote notifications, I have enabled CloudKit and my Container. I have checked with CloudKit dashboard that the changes are uploaded into the cloud pretty fast. It seems that they aren't downloaded to the devices so quickly.

What else do I have to do to get this working? Like enter data in one device and in less than a minute it appears on the other device. A background service maybe?


Solution

  • OMG. I found the answer myself. In PersistenceController at the end I added:

    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    container.viewContext.automaticallyMergesChangesFromParent = true
    

    Credit: schwiftyui.com