2014-07-16 10 views
6

Я пытаюсь создать тип записи, содержащий уникальные значения, и будет выступать в качестве целевых объектов ссылки в другой тип записи. Например, Тип записи - Фильмы будет содержать уникальный список фильмов, предоставляемых пользователями. И FavoriteMovies будет содержать ссылку «Пользователи» и ссылку на фильмы. Пользователи могли выбирать из списка существующих фильмов или добавлять к нему новые.CloudKit - Как сохранить запись, если не существует

Проблема возникает, если я создаю новую запись Кино, в то время как другой пользователь создает новую запись с тем же именем (после того как я получил список фильмов, но до того, как я попытаюсь добавить новый). Две новые записи считаются разными записями с разными идентификаторами записи. Это означает, что как только я сохраню новый, будут два экземпляра фильмов с именем сохранения.

Я не могу найти способ выполнить операцию «Сохранить, если нет», чтобы напечатать операцию с типом записи фильмов. Я мог бы сэкономить в завершении запроса запроса, но эти два действия не были бы атомной транзакцией, чтобы гарантировать уникальность. Насколько я знаю, это также относится к цепочке CKQueryOperation с CKModifyRecordsOperation.

Есть ли способ вставить запись, только если значение не существует в одной транзакции?

ответ

6

Если я правильно понял ваш случай использования, вы можете сделать movieRecord.recordID.recordName название фильма и использовать CKModifyRecordsOperation с savePolicyIfServerRecordUnchanged эффективно Сохранить Если не существует. Затем он будет возвращать ошибку, что вы можете игнорировать, если вы пытаетесь сохранить запись, которая уже существует на сервере:

let saveRecordsOperation = CKModifyRecordsOperation() 
saveRecordsOperation.recordsToSave = [movieRecord] 
saveRecordsOperation.savePolicy = .IfServerRecordUnchanged 

С savePolicy IfServerRecordUnchanged эта операция позволит сэкономить новый рекорд фильма, если он еще не существует на сервере («Сохранить, если не существует»), но вернет ошибку ниже при любой последующей попытке перезаписать записанную на сервере запись о фильме (при условии, что она не является новой модифицированной версией записи, полученной с сервера):

<CKError 0x14d23980: "Server Record Changed" (14/2017); server message = "record to insert already exists"> 

вы могли бы справиться с этим конфликтом в perRecordCompletionBlock, но в вашем конкретном случае использования вы может просто ничего не делать с ошибкой конфликта, поэтому каждая запись фильма будет первой сохраненной записью с этим CKRecordID.

+0

К сожалению, это не работает для меня. Я создаю новый экземпляр movieRecord для добавления в список. Если другой пользователь создал запись с тем же именем (после того как я получил список фильмов, но до того, как я попытаюсь добавить новый), они считаются разными записями, так как они имеют разные идентификаторы записи. Это означает, что даже если моя savePolicy установлена ​​на IfServerRecordUnchanged, операция не вызывает ошибку. Вместо этого я бы увидел две разные записи с тем же именем. – Denis

+0

Получил это. Это будет работать, если вы сделали movieRecord.recordID.recordName названием фильма. У меня есть аналогичный случай использования с использованием базы данных Public, и это то, что я делаю, чтобы сделать публичные записи уникальными. Я сделал редактирование ответа, чтобы отметить это предположение. –

+0

Хорошая идея, эта работа вокруг сделает это для меня. Благодаря! – Denis