Russ
Russ

Reputation: 576

Core Data and CloudKit sync is inconsistent

I have an app that uses Core Data and CloudKit using the public database. The problem is that deletes never seem to sync and additions and changes don't show up until the app enters the background and then returns to the foreground, and even those results are inconsistent.

The example app is just the default app you get when specifying SwiftUI and Core Data. I modified the Schema in the CloudKit dashboard to add the two indexes recordName and modifiedAt.

The following is the Persistence.swift file, so to reproduce, create a new project, chose Core Data and Use CloudKit, Add Capability for CloudKit and Remote Notifications, then replace the Persistence.swift contents with the above.

import CoreData

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        for _ in 0..<10 {
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()
        }
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentCloudKitContainer

    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "TestCKSink")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        
        guard let description = container.persistentStoreDescriptions.first else
        {
            fatalError()
        }
        //description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        description.cloudKitContainerOptions?.databaseScope = .public
        container.viewContext.transactionAuthor = "Me"
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {

                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
}

I have tried this with and without the history tracking option turned on. As I said, this works some of the time. I also realize that I need to add code to force refresh the display, but even checking the CloudKit dashboard and querying the records, some do not don't show there at all or take a long time to arrive (18 minutes).

Any suggestions would be welcomed.

Upvotes: 0

Views: 647

Answers (1)

Sebastian
Sebastian

Reputation: 497

I experienced similar issues some time ago, try the following setting when initializing your managed object context:

managedObjectContext.automaticallyMergesChangesFromParent = true

Upvotes: 1

Related Questions