I am trying to make a Record Type that contains unique values, and would act as the target reference objects to another Record Type. For example, Record Type - Movies would contain unique list of movies submitted by users. And FavoriteMovies would contain a Users reference and a Movies reference. Users could select from a list of existing Movies, or add new ones to it.
The problem happens if I create a new Movies record, while another user creates a new record with the same name (after I retrieved the list of movies, but before I attempt to add a new one). The two new records are considered different records with different recordIDs. This means that once I saved the new one, there will be two instances of Movies with the save name.
I'm not able to find a way to perform a Save If Not Exists type operation to the Movies Record Type. I could do a save in the completionBlock of a query, but those two actions would not be an atomic transaction to guarantee uniqueness. As far as I know this is also the case with chaining CKQueryOperation
with CKModifyRecordsOperation
.
Is there a way to insert a record only if the value does not exists in a single transaction?
If I understood correctly your use case, you can make movieRecord.recordID.recordName the movie's name and use CKModifyRecordsOperation
with savePolicy
IfServerRecordUnchanged
to effectively Save If Not Exists. It would then return an error that you can ignore if you try to save a record that already exists on the server:
let saveRecordsOperation = CKModifyRecordsOperation()
saveRecordsOperation.recordsToSave = [movieRecord]
saveRecordsOperation.savePolicy = .IfServerRecordUnchanged
With the savePolicy IfServerRecordUnchanged
this operation will save a new Movie record if it doesn't exist yet on the server (Save If Not Exists) but will return the error below on any subsequent try to overwrite a Movie record that already exists on the server (provided it is not a newer modified version of a record that was fetched from the server):
<CKError 0x14d23980: "Server Record Changed" (14/2017); server message = "record to insert already exists">
You could deal with this conflict in the perRecordCompletionBlock
but in your specific use case you can just do nothing about the conflict error so each Movie record will be the first saved record with that CKRecordID.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With