CloudKit - не удалось изменить существующий CKRecord с моим собственным CKRecord.ID, хотя удаление работает.

Для каждой записи, которую я сохраняю в 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: «Частичный отказ» (2/1011); «Не удалось изменить некоторые записи»; uuid = 9A077F5D-AB44-412C-9B87-BFBAE3C7B19B; ID контейнера = "iCloud.com.xxx.yyy"; частичные ошибки: {CC0A0279-F511-4EF4-BF89-4A3072EA1AEF:(_defaultZone:defaultOwner)= <CKError 0x600000b80240: «Запись сервера изменена» (14/2004); server message = "запись для вставки уже существует"; 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, который я использовал для создания записи? Операция удаления четко распознает это.

1 ответ

Решение

В общем, вы всегда должны получать CKRecordобъект из серверной части вместо того, чтобы создавать его в памяти. Только так Cloudkit правильно его инициализирует.

Где код, который дает вам эту запись, а не следующий код?

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

При желании проверьте политику сохранения записей .

Подробнее см. В этом ответе .

Другие вопросы по тегам