代码之家  ›  专栏  ›  技术社区  ›  ACerts

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

  •  0
  • ACerts  · 技术社区  · 6 年前

    我在保存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: {
    
        })   
    }
    

    这两种方法 deckToCKRecord() cardToCKRecord() 是我用来将核心数据转换为CKRecord以便共享的数据。非常感谢。

    1 回复  |  直到 6 年前
        1
  •  4
  •   Bill    6 年前

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

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

    大多数人使用的第二种更普遍的方法是 CKFetchRecordsOperation 根记录的 share var记录ID。全部的 CKRecord 对象具有 共有 var,即 CKReference ,但如果对象尚未共享,则该值将为零。如果我是对的,在取消后的第二次尝试中,您将发现根记录的共享引用包含您在第一次尝试中设置的CKShare。所以,抓住那份分享,然后用它,像以前一样开始你的父母和其他参考!