4
<CKError 0x14d8cb70: "Partial Failure" (2/1011); "Failed to modify some records"; partial errors: { B5DEF0B5-F064-4B27-9C89-BE75C9134297:(_defaultZone:__defaultOwner__) = <CKError 0x14d83b70: "Server Record Changed" (14/2037); "Error saving record <CKRecordID: 0x15748cd0; B5DEF0B5-F064-4B27-9C89-BE75C9134297:(_defaultZone:__defaultOwner__)> to server: Protection data didn't match"> }> 

I get this error, when try to save CKRecords up to CloudKit. Any idea?

Do I have to fetch first records like in convenience API?

I am using CKModifyRecordsOperation method to update more record.

1 Answer 1

7

When you are planning to do an update, you first need to read the record, make the changes and then write the record. You got a notification that the record was changed in the time between reading and writing the record.

If the version of a record on the server is newer than the version you tried to save, the server returns a CKErrorServerRecordChanged error. The userInfo dictionary of the error object contains the different versions of the conflicting records. Use these keys to retrieve the records and to perform whatever resolution logic is needed to resolve the conflict.

As discussed below in your case the problem was that you persisted the object to a database and recreated the CKRecord to do the modification. In that case you need to persist the system fields using CKRecord encodeSystemFieldsWithCoder. And recreate the CKRecord by initializing it with a NSCoder. You could use the NSKeyedArchiver and NSKeyedUnarchiver for saving a CKRecord and recreating it. If you need a sample, see the fromCKRecord and toCKRecord methods at the bottom of https://github.com/evermeer/EVCloudKitDao/blob/master/AppMessage/AppMessage/CloudKit/EVCloudKitDao.swift

Sign up to request clarification or add additional context in comments.

12 Comments

for 1 record it is ok, but for updating 100-s of records, is it serious I have to download first, find which one how to modify, and upload ?? brbrbr
You don't have to read them again. see my updated answer. So just save them all and try the update again when you get an error using the record ID's inside the error
You can use -[CKRecord encodeSystemFieldsWithCoder:] to encode just the system fields (like the change tag) for a record. You can later unarchive the record with just the system fields, apply just the changes you want saved to the server, and save the record. If you're already keeping a local database of records that should save you a round trip to the server.
I do as you say, (1) reading (2) modifying CKRecords (3) saving, and I do it with a certain set of records quite frequently, and sometimes I receive only part of the records, not all for what I specified condition in CKQuery's predicate, do you know why?
The result that is returned by CloudKit is limited. The standard number of records seems to be 100, but that can vary depending on how the total load on iCloud is. If you use a SKQueryOperation, then you can influence the number of records that needs to be returned by setting .resultsLimit The default value for that is CKQueryOperationMaximumResults
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.