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)
При желании проверьте политику сохранения записей .
Подробнее см. В этом ответе .