【问题标题】:CloudKit - How to Save Record If Not ExistsCloudKit - 如果不存在,如何保存记录
【发布时间】:2014-09-07 05:53:49
【问题描述】:

我正在尝试创建一个包含唯一值的记录类型,并将充当另一个记录类型的目标引用对象。例如,记录类型 - 电影将包含用户提交的唯一电影列表。并且 FavoriteMovies 将包含一个用户引用和一个电影引用。用户可以从现有电影列表中进行选择,或向其中添加新电影。

如果我创建了一个新的电影记录,而另一个用户创建了一个具有相同名称的新记录(在我检索到电影列表之后,但在我尝试添加新列表之前),就会出现问题。这两个新记录被视为具有不同记录 ID 的不同记录。这意味着一旦我保存了新的,就会有两个具有保存名称的 Movies 实例。

我无法找到对电影记录类型执行“如果不存在则保存”类型操作的方法。我可以在查询的完成块中保存,但这两个操作不会是保证唯一性的原子事务。据我所知,将CKQueryOperationCKModifyRecordsOperation 链接也是如此。

有没有办法只在单个事务中不存在值时才插入记录?

【问题讨论】:

    标签: ios icloud ios8 cloudkit


    【解决方案1】:

    如果我正确理解了您的用例,您可以将 movieRecord.recordID.recordName 设为电影的名称,并使用 CKModifyRecordsOperationsavePolicy IfServerRecordUnchanged 来有效地保存如果不存在。如果您尝试保存服务器上已存在的记录,它将返回一个您可以忽略的错误:

    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 的第一个保存记录。

    【讨论】:

    • 不幸的是,这对我不起作用。我正在创建一个新的movieRecord 实例以添加到列表中。如果另一个用户创建了一个同名的记录(在我检索到电影列表之后,但在我尝试添加一个新的之前),它们被认为是不同的记录,因为它们具有不同的记录 ID。这意味着即使我的 savePolicy 设置为 IfServerRecordUnchanged,该操作也不会引发错误。相反,我会看到两个具有相同名称的不同记录。
    • 知道了。如果您将movieRecord.recordID.recordName 设为电影的名称,它将起作用。我有一个使用公共数据库的类似用例,这就是我为保持公共记录的唯一性所做的事情。我对答案进行了编辑以注意该假设。
    • 好主意,这项工作将为我解决。谢谢!
    猜你喜欢
    • 2014-11-30
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2016-12-14
    • 2014-12-28
    • 2014-12-09
    相关资源
    最近更新 更多