CKShare "Server record changed" 错误
CKShare "Server record changed" error
我在保存 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()
这两个方法是我用来从Core Data转换成CKRecord的,这样就可以共享了。谢谢。
有可能即使共享操作被取消(因为您没有明确说明取消的意思),您设置的 CKShare 记录实际上已创建并保存在您的私人数据库中。您只是取消了更改其他用户的参与状态(例如受邀)。因此,当您重复此过程时,您正在尝试 re-save 相同的 CKShare,尽管再次设置因此可能会修改更改标签。 CloudKit 看到这个并且 returns 一个 "Server Record Changed" 错误。
如果我是对的,你可以用两种方法之一来处理这个问题。首先,将 CKModifyRecordsOperation
变量 savePolicy
的值设置为 .allKeys
,例如,就在您设置 qualityOfService
变量的位置。这将强制即使 CloudKit 在您的服务器上找到记录,它也会自动覆盖它。如果您确定上传的版本应该总是获胜,这是一个很好的方法(并且只会产生一个网络调用)。
大多数人使用的第二种更通用的方法是首先使用根记录的 share
var recordID 创建一个 CKFetchRecordsOperation
。所有 CKRecord
object 都有一个 share
var,它是一个 CKReference
,但如果 object 尚未共享,则这将为 nil。如果我是对的,在取消后的第二次尝试中,您会发现根记录的共享引用包含您在第一次尝试时设置的 CKShare。因此,抓住那份份额,然后像以前一样启动其余的 parent 和其他参考资料!
我在保存 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()
这两个方法是我用来从Core Data转换成CKRecord的,这样就可以共享了。谢谢。
有可能即使共享操作被取消(因为您没有明确说明取消的意思),您设置的 CKShare 记录实际上已创建并保存在您的私人数据库中。您只是取消了更改其他用户的参与状态(例如受邀)。因此,当您重复此过程时,您正在尝试 re-save 相同的 CKShare,尽管再次设置因此可能会修改更改标签。 CloudKit 看到这个并且 returns 一个 "Server Record Changed" 错误。
如果我是对的,你可以用两种方法之一来处理这个问题。首先,将 CKModifyRecordsOperation
变量 savePolicy
的值设置为 .allKeys
,例如,就在您设置 qualityOfService
变量的位置。这将强制即使 CloudKit 在您的服务器上找到记录,它也会自动覆盖它。如果您确定上传的版本应该总是获胜,这是一个很好的方法(并且只会产生一个网络调用)。
大多数人使用的第二种更通用的方法是首先使用根记录的 share
var recordID 创建一个 CKFetchRecordsOperation
。所有 CKRecord
object 都有一个 share
var,它是一个 CKReference
,但如果 object 尚未共享,则这将为 nil。如果我是对的,在取消后的第二次尝试中,您会发现根记录的共享引用包含您在第一次尝试时设置的 CKShare。因此,抓住那份份额,然后像以前一样启动其余的 parent 和其他参考资料!