Ios CKShare";“服务器记录已更改”;错误

Ios CKShare";“服务器记录已更改”;错误,ios,swift,cloudkit,Ios,Swift,Cloudkit,我在保存CKShare时遇到问题。执行共享时,一切正常,但如果共享被取消并尝试再次共享,我将收到错误: "Server Record Changed" (14/2004); server message = "client oplock error updating record" 以下是我的共享代码: func share(_ deck: Deck) { let zoneID = CKManager.defaultManager.sharedZone?.zoneID i

我在保存CKShare时遇到问题。执行共享时,一切正常,但如果共享被取消并尝试再次共享,我将收到错误:

"Server Record Changed" (14/2004); server message = "client oplock error updating record"
以下是我的共享代码:

func share(_ deck: Deck) {

    let zoneID = CKManager.defaultManager.sharedZone?.zoneID


    if let deckName = deck.name {
        selectedDeckForPrivateShare = deckName
    }

    var records = [CKRecord]()


    let deckRecord = deck.deckToCKRecord(zoneID)

    records.append(deckRecord)


    let reference = CKReference(record: deckRecord, action: .none)

    for index in deck.cards {
        let cardRecord = index.cardToCKRecord(zoneID)
        cardRecord["deck"] = reference
        cardRecord.parent = reference

        records.append(cardRecord)

    }


    let share = CKShare(rootRecord: deckRecord)
    share[CKShareTitleKey] = "\(String(describing: deck.name)))" as CKRecordValue?
    records.append(share)
    let sharingController = UICloudSharingController { (controller, preparationCompletion) in


        let modifyOP = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: nil)

        modifyOP.qualityOfService = .userInteractive
        modifyOP.modifyRecordsCompletionBlock = { (savedRecords,deletedRecordIDs,error) in
            preparationCompletion(share, CKContainer.default(), error)

            controller.delegate = self

            if let error = error {
                print(error)

            }
        }


        self.privateDatabase.add(modifyOP)

    }


    sharingController.delegate = self

    self.present(sharingController, animated: true, completion: {

    })   
}

我使用这两种方法将核心数据转换为CKRecord,以便共享。谢谢。

即使共享操作被取消(因为您没有明确说明取消的意思),您设置的CKShare记录也可能被创建并保存在您的私有数据库中。您只是取消了更改其他用户的参与状态(如已邀请)。因此,当您重复此过程时,您正在尝试重新保存相同的CKShare,尽管再次设置可能会修改更改标记。CloudKit看到这一点并返回“服务器记录已更改”错误

如果我是对的,你可以用两种方法中的一种来处理。首先,将
CKModifyRecordsOperation
变量
savePolicy
的值设置为
。例如,在设置
qualityOfService
变量的地方,所有键都将设置为
。这将强制要求即使CloudKit在您的服务器上找到该记录,它也会自动覆盖该记录。如果你确信上传的版本总是会赢,这是一个好方法(并且只会导致一次网络呼叫)


大多数人使用的第二种更通用的方法是首先使用根记录的
共享
var recordID进行
ckfetchrecordsooperation
。所有
CKRecord
对象都有一个
share
var,它是
CKReference
,但如果对象尚未共享,则该值将为零。如果我是对的,在取消后的第二次尝试中,您将发现根记录的共享引用包含您在第一次尝试中设置的CKShare。因此,抓住那份分享,然后用它,开始你的父母和其他参考的其余部分,就像你以前做的那样

即使共享操作被取消(因为您没有明确说明取消的意思),您设置的CKShare记录也可能被创建并保存在您的私有数据库中。您只是取消了更改其他用户的参与状态(如已邀请)。因此,当您重复此过程时,您正在尝试重新保存相同的CKShare,尽管再次设置可能会修改更改标记。CloudKit看到这一点并返回“服务器记录已更改”错误

如果我是对的,你可以用两种方法中的一种来处理。首先,将
CKModifyRecordsOperation
变量
savePolicy
的值设置为
。例如,在设置
qualityOfService
变量的地方,所有键都将设置为
。这将强制要求即使CloudKit在您的服务器上找到该记录,它也会自动覆盖该记录。如果你确信上传的版本总是会赢,这是一个好方法(并且只会导致一次网络呼叫)

大多数人使用的第二种更通用的方法是首先使用根记录的
共享
var recordID进行
ckfetchrecordsooperation
。所有
CKRecord
对象都有一个
share
var,它是
CKReference
,但如果对象尚未共享,则该值将为零。如果我是对的,在取消后的第二次尝试中,您将发现根记录的共享引用包含您在第一次尝试中设置的CKShare。因此,抓住那份分享,然后用它,开始你的父母和其他参考的其余部分,就像你以前做的那样