I am working with CoreData and WidgetKit. I would like to implement a NSPersistentCloudKitContainer into an interactive widget. However, when the user makes a change over the widget, the container does not sync the data until the user launches the app. I noticed an error:
error: CoreData+CloudKit: -NSCloudKitMirroringDelegate resetAfterError:andKeepContainer:: <NSCloudKitMirroringDelegate: 0x12f36e8e0> – resetting internal state after error: Error Domain=NSCocoaErrorDomain Code=134407 “Request ‘XYZ’ was cancelled because the store was removed from the coordinator.” UserInfo={NSLocalizedFailureReason=Request ‘XYZ’ was cancelled because the store was removed from the coordinator.}
I have found a potential solution: Migrating Data to App Groups Disables iCloud Syncing. However, it still does not work.
Here is the code of configuration the NSPersistentCloudKitContainer:
let container = NSPersistentCloudKitContainer(name: "X")
guard let privateStoreDescription = container.persistentStoreDescriptions.first else {
fatalError("#\(#function): Failed to retrieve a persistent store description.")
}
let storesURL = //...
privateStoreDescription.url = storesURL.appendingPathComponent("private.sqlite")
privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
let sharedStoreURL = storesURL.appendingPathComponent("shared.sqlite")
guard let sharedStoreDescription = privateStoreDescription.copy() as? NSPersistentStoreDescription else {
fatalError("#\(#function): Copying the private store description returned an unexpected value.")
}
sharedStoreDescription.url = sharedStoreURL
let containerIdentifier = privateStoreDescription.cloudKitContainerOptions!.containerIdentifier
let sharedStoreOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: containerIdentifier)
sharedStoreOptions.databaseScope = .shared
sharedStoreDescription.cloudKitContainerOptions = sharedStoreOptions
container.persistentStoreDescriptions.append(sharedStoreDescription)
container.loadPersistentStores(completionHandler: { (loadedStoreDescription, error) in
if let loadError = error as NSError? {
fatalError("\(#function): Failed to load persistent stores:\(loadError)")
} else if let cloudKitContainerOptions = loadedStoreDescription.cloudKitContainerOptions {
if .private == cloudKitContainerOptions.databaseScope {
self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: loadedStoreDescription.url!)
} else if .shared == cloudKitContainerOptions.databaseScope {
self._sharedPersistentStore = container.persistentStoreCoordinator.persistentStore(for: loadedStoreDescription.url!)
}
}
})
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.transactionAuthor = CoreDataStack.appAuthor
container.viewContext.automaticallyMergesChangesFromParent = true
do {
try container.viewContext.setQueryGenerationFrom(NSQueryGenerationToken.current)
} catch {
fatalError("\(#function): Failed to pin viewContext to the current generation:\(error)")
}
return container
Localisation of the stores is based on the App Group.
Thanks in advance!