CloudKit公共数据库是否支持原子保存?批量保存部分生效问题咨询
CloudKit公共数据库原子保存问题解答
核心结论
CloudKit公共数据库支持原子批量保存,但有个关键前提:所有要批量操作的CKRecord必须属于同一个自定义公共Zone。默认的公共根Zone(CKRecordZone.default())不支持原子操作,这就是你设置isAtomic = true后仍出现部分保存的原因。
问题根源分析
你当前代码中获取的articleRecord、favoriteRecord、pointRecord大概率来自默认公共根Zone,而原子操作仅对自定义Zone内的记录生效。另外,你的错误处理逻辑存在疏漏:当遇到.zoneNotFound错误时直接return,没有将错误传递给上层completion,导致调用方无法感知到原子操作失败。
修复方案
1. 确保记录在自定义公共Zone中
首先需要创建并使用自定义公共Zone,所有要批量保存的记录必须属于这个Zone:
// 创建自定义公共Zone let customPublicZone = CKRecordZone(zoneName: "YourCustomPublicZone") // 初始化或更新记录时指定Zone let articleRecord = CKRecord(recordType: "Article", recordID: CKRecord.ID(recordName: "articleID", zoneID: customPublicZone.zoneID)) // 同理处理favoriteRecord和pointRecord
2. 修正操作逻辑与错误处理
调整saveDeleteOperation函数,确保错误能正确传递,同时确认操作针对自定义Zone:
public func saveDeleteOperation(saveRecords: [CKRecord], deleteRecords: [CKRecord.ID], completion: @escaping (Error?) -> Void) { guard !saveRecords.isEmpty else { completion(nil) return } // 校验所有记录是否属于同一个Zone(原子操作要求) let firstZoneID = saveRecords.first!.recordID.zoneID guard saveRecords.allSatisfy({ $0.recordID.zoneID == firstZoneID }) else { completion(NSError(domain: "CloudKitError", code: -1, userInfo: [NSLocalizedDescriptionKey: "所有记录必须属于同一个Zone才能执行原子操作"])) return } let modifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: saveRecords, recordIDsToDelete: deleteRecords) modifyRecordsOperation.isAtomic = true // 显式指定操作的Zone,确保原子性生效 modifyRecordsOperation.configuration.zoneID = firstZoneID modifyRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in guard error == nil else { guard let ckError = error as? CKError else { completion(error) return } if ckError.code == .partialFailure { // 原子操作下,partialFailure意味着整体失败,不存在部分保存 if let partialErrors = ckError.partialErrorsByItemID { for (recordID, itemError) in partialErrors { log("记录\(recordID.recordName)操作失败:\(itemError.localizedDescription)") } } completion(ckError) } else { completion(ckError) } return } log("批量原子保存完成,成功保存\(savedRecords?.count ?? 0)条记录") completion(nil) } self.publicDB.add(modifyRecordsOperation) }
3. 调用端注意事项
确保你获取的记录都来自同一个自定义公共Zone,若之前的记录存储在默认Zone,需要先迁移到自定义Zone后再执行原子操作。
内容的提问来源于stack exchange,提问作者Good Question
相关产品推荐
相关产品推荐

