Both methods experience delays when synchronizing a large amount of data at once.
We are using two methods:
During the initial installation, we call the below code to receive synchronization data and provide a user experience indicating that synchronization is in progress.
public extension NSPersistentCloudKitContainer {
func waitForCloudKitEvents(timeout: Int) async throws -> NSPersistentCloudKitContainer.Event? {
let affectedStores = persistentStoreDescriptions
.filter { description in
description.cloudKitContainerOptions != nil
}
.compactMap { description -> NSPersistentStore? in
guard let url = description.url else { return nil }
return persistentStoreCoordinator.persistentStore(for: url)
}
let context = newBackgroundContext()
let request = NSPersistentCloudKitContainerEventRequest.fetchEvents(after: .distantPast)
request.resultType = .events
request.affectedStores = affectedStores
for seconds in 0...timeout {
await Task.sleep(seconds: 1)
let results: NSPersistentStoreResult = try context.execute(request)
// find event.
if let results = results as? NSPersistentCloudKitContainerEventResult,
let events = results.result as? [NSPersistentCloudKitContainer.Event],
let event = (events.first { $0.succeeded && $0.type == .import }) {
return event
}
}
throw CoreDataError.cloudKitEventTimeOut
}
}
For regular data synchronization (upload, download), we use the typical approach of receiving synchronization data using CloudKitContainer and NSPersistentCloudKitContainer.eventChangedNotification.
(We employ a structure similar to the Apple CoreData synchronization example.)