【问题标题】:CloudKit - Failed to modify existing CKRecord with my own CKRecord.ID, even though delete worksCloudKit - 无法使用我自己的 CKRecord.ID 修改现有的 CKRecord,即使删除有效
【发布时间】:2021-09-28 07:48:09
【问题描述】:

对于我保存到 CloudKit 的每条记录,我都会传入一个使用我自己的 UUID 生成的 CKRecord.ID,如下所示:

        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":

defaultOwner) = }>

这是我的修改代码:

    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 来修改现有记录?删除操作清楚地识别它。

【问题讨论】:

  • 您有一些严重的问题。第 1 号,您没有使用您指定的记录 ID 修改记录。 2号,下面这行是什么? record.setObject(item.title as __CKRecordObjCValue, forKey: "title") 这只是几个。您可能还有更多问题。
  • @ElTomato 所以,看起来我通过以下方式获得的记录:let record = CKRecord(recordType: recordType, recordID: recordId) 与通过调用fetch(withRecordID: recordID) { } 获得的记录不同。我更改了我的代码以首先进行提取,并且修改有效。必须始终先进行提取吗?似乎应该有一种方法可以修改 withRecordID。
  • 实际上,您正在尝试使用现有 id 创建一个新的。

标签: swift cloudkit ckmodifyrecordsoperation


【解决方案1】:

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

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

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

或者,检查record save policy

欲知详情,see this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    相关资源
    最近更新 更多