如何在CoreData+CloudKit场景下检测iCloud存储配额超限?
检测iCloud存储配额超限的可行方案
问题背景
当iCloud存储已满时,CoreData + CloudKit同步会抛出Quota Exceeded(错误码25/2035),但常规同步回调可能无法直接捕获该错误,导致无法及时向用户展示提示。
解决方案
1. 监听CoreData CloudKit镜像代理通知
CoreData的CloudKit镜像代理会发送同步相关通知,可通过NotificationCenter监听NSCloudKitMirroringDelegateDidFinishExportingChangesNotification,从通知的userInfo中提取错误信息:
NotificationCenter.default.addObserver(forName: NSCloudKitMirroringDelegateDidFinishExportingChangesNotification, object: persistentContainer.cloudKitMirroringDelegate, queue: .main) { notification in guard let userInfo = notification.userInfo, let error = userInfo[NSCloudKitMirroringExportErrorKey] as? NSError else { return } // 解析CKError if let ckError = CKError(_nsError: error) { if ckError.code == .quotaExceeded { // 触发配额超限提示 showQuotaExceededAlert() } else if ckError.code == .partialFailure, let partialErrors = ckError.partialErrorsByItemID { // 检查部分错误中是否包含配额超限 for (_, partialError) in partialErrors { if let partialCKError = CKError(_nsError: partialError as NSError), partialCKError.code == .quotaExceeded { showQuotaExceededAlert() break } } } } }
2. 主动查询CloudKit配额使用状态
使用CloudKit原生API直接查询当前配额使用情况,提前判断是否即将超限:
let container = CKContainer.default() container.fetchQuotaUsageWithCompletionHandler { usedBytes, error in guard error == nil else { // 处理查询错误 return } // 获取总配额并计算使用率 container.accountStatus { status, accountError in if status == .available { container.fetchAccountInfo { accountInfo, infoError in guard let accountInfo = accountInfo else { return } let totalBytes = accountInfo.quotaBytes let usagePercentage = (Double(usedBytes) / Double(totalBytes)) * 100 if usagePercentage > 90 { // 可自定义阈值,比如超过90%时提示 DispatchQueue.main.async { showQuotaWarningAlert() } } } } } }
3. 捕获CoreData保存时的深层错误
在CoreData保存操作的回调中,递归解析错误链,查找是否包含CKError.quotaExceeded:
context.save { success, error in if let error = error { var currentError: Error = error // 遍历错误链,获取底层CKError while let underlyingError = currentError._userInfo[NSUnderlyingErrorKey] as? Error { currentError = underlyingError if let ckError = currentError as? CKError, ckError.code == .quotaExceeded { showQuotaExceededAlert() break } } } }
注意事项
- 需在
NSPersistentCloudKitContainer初始化完成后再设置通知监听。 - 部分错误会被CoreData多层包装,需通过
NSUnderlyingErrorKey递归解析原始CKError。 - 主动查询配额的方法依赖用户已登录iCloud账号,需先检查
CKAccountStatus。
内容的提问来源于stack exchange,提问作者Russ Neufeld
相关产品推荐
相关产品推荐

