CloudKit: how to handle CKError partialFailure when using NSPersistentCloudKitContainer?

282 views Asked by At

I'm using NSPersistentCloudKitContainer with Core Data and I receive errors because my iCloud space is full. The errors printed are the following: <CKError 0x280df8e40: "Quota Exceeded" (25/2035); server message = "Quota exceeded"; op = 61846C533467A5DF; uuid = 6A144513-033F-42C2-9E27-693548EF2150; Retry after 342.0 seconds>.

I want to inform the user about this issue, but I can't find a way to access the details of the error. I'm listening to NSPersistentCloudKitContainer.eventChangedNotification, I receive a error of type .partialFailure. But when I want to access the underlying errors, the partialErrorsByItemID property on the error is nil.

How can I access this Quota Exceeded error?

import Foundation
import CloudKit
import Combine
import CoreData

class SyncMonitor {
    fileprivate var subscriptions = Set<AnyCancellable>()

    init() {
        NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification)
            .sink { notification in
                if let cloudEvent = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey] as? NSPersistentCloudKitContainer.Event {

                    guard let ckerror = cloudEvent.error as? CKError else {
                        return
                    }
                
                    print("Error: \(ckerror.localizedDescription)")
                    if ckerror.code == .partialFailure {
                        guard let errors = ckerror.partialErrorsByItemID else {
                            return
                        }
                    
                        for (_, error) in errors {
                            if let currentError = error as? CKError {
                                print(currentError.localizedDescription)
                            }
                        }
                    }
                
                }
            } // end of sink
            .store(in: &subscriptions)
    }
}
0

There are 0 answers