CloudKit - 无法使用我自己的 CKRecord.ID 修改现有的 CKRecord,即使删除有效

CloudKit - Failed to modify existing CKRecord with my own CKRecord.ID, even though delete works

对于我保存到CloudKit的每条记录,我传入一个CKRecord.ID,它是使用我自己的UUID制作的,如下所示:

        let recordId = CKRecord.ID(recordName: myOwnUUID, zoneID: .default)
        let record = CKRecord(recordType: recordType, recordID: recordId)
        record.setValue(title, forKey: "title")
        ...

UUID 是我的数据模型的一部分,不会针对每条记录更改。

我能够成功删除记录,再次传入相同的CKRecord.ID:

    func delete(_ item: MyItem, completion: @escaping (Result<Int, Error>) -> ()) {

        let myOwnUUID = item.id // this is the exact same UUID that I used to create/save the record the first time.
        let recordId = CKRecord.ID(recordName: myOwnUUID, zoneID: .default)

        ckDatabase.delete(withRecordID: recordId) { (recordId, error) in
            DispatchQueue.main.async {
                if let error = error {
                    completion(.failure(error))
                    return
                }
                guard recordId != nil else {
                    completion(.failure(CloudKitHelperError.castFailure))
                    return
                }
                completion(.success(0))
            }
        }
    }

所以,删除作品没有任何问题。

但是当我尝试 修改 记录时,我收到错误消息:"Server Record Changed"... "record to insert already exists":

<CKError 0x600000b82af0: "Partial Failure" (2/1011); "Failed to modify some records"; uuid = 9A077F5D-AB44-412C-9B87-BFBAE3C7B19B; container ID = "iCloud.com.xxx.yyy"; partial errors: { CC0A0279-F511-4EF4-BF89-4A3072EA1AEF:(_defaultZone:defaultOwner) = <CKError 0x600000b80240: "Server Record Changed" (14/2004); server message = "record to insert already exists"; uuid = 9A077F5D-AB44-412C-9B87-BFBAE3C7B19B> }>

这是我的修改代码:

    func modify(_ item: MyItem, completion: @escaping (Result<Int, Error>) -> ()) {

        let myOwnUUID = item.id // this is the exact same UUID that I used to create/save the record the first time.
        let recordId = CKRecord.ID(recordName: myOwnUUID, zoneID: .default)

        let record = CKRecord(recordType: recordType, recordID: recordId)
        
        record.setObject(item.title as __CKRecordObjCValue, forKey: "title")

        let configuration = CKOperation.Configuration()
        configuration.timeoutIntervalForRequest = 10
        configuration.timeoutIntervalForResource = 10

        let operation = CKModifyRecordsOperation(recordsToSave: [record], recordIDsToDelete: nil)
        operation.configuration = configuration
        
        operation.modifyRecordsCompletionBlock = { (savedRecords, _, error) in
            DispatchQueue.main.async {
                if savedRecords != nil, error == nil {
                    completion(.success(0))
                }
                if let error = error {
                    completion(.failure(error))
                }
            }
        }
        
        ckDatabase.add(operation)
    }

顺便说一句,ckDatabase设置为:ckDatabase = CKContainer(identifier: "iCloud.com.xxx.yyy").privateCloudDatabase

那么,为什么我不能使用创建记录时使用的 CKRecord.ID 修改现有记录?删除操作清晰识别。

一般来说,您应该始终从后端获取 CKRecord 对象,而不是在内存中构造它。只有这样,cloudkit 才能正确初始化它。

首先给你这条记录的代码在哪里,而不是下面的代码?

let record = CKRecord(recordType: recordType, recordID: recordId)

(可选)检查 record save policy

详情,see this answer.