0

我有一个“赞”按钮,所有用户同时使用它。它应该将云容器中类似记录的值加一,或减一。如何保证更新发生在记录的最后一个版本?我的意思是 Swift 3 中的代码是什么,它可以保证每个用户都将获得类似记录的最终值并应用增量,而其他用户在同一记录上发送相同的操作?对不起,我没有代码可以显示这个。

我读过CKErrorServerRecordChanged但我不知道如何在语法中使用它。如果您有代码示例,那就太好了。

我在 Firebase 中找到了它。它被称为事务,它会一直跟踪记录版本,直到将操作应用于最后一个版本,这样它就不会丢失任何针对该记录的用户操作。

4

1 回答 1

1

好的,不确定这是一个剪切粘贴的答案,但会给你一个模板来使用。它显示了广泛的错误代码处理,在重试旁边有一个动作,例如保存动作。您应该能够弄清楚如何使用此代码执行您想要执行的操作。

func files_saveSet() {
    let newRecord = CKRecord(recordType: "Blah", recordID: sharedDataAccess.iCloudID)
    newRecord["Key"] = sharedDataAccess.iCloudLink as CKRecordValue?

    var localChanges:[CKRecord] = []
    let records2Erase:[CKRecordID] = []
    localChanges.append(newRecord)

    let saveRecordsOperation = CKModifyRecordsOperation(recordsToSave: localChanges, recordIDsToDelete: records2Erase)
    saveRecordsOperation.savePolicy = .changedKeys
    saveRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
        self.theApp.isNetworkActivityIndicatorVisible = false
        guard error == nil else {
            if let ckerror = error as? CKError {
                if ckerror.code == CKError.requestRateLimited {
                    let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                        DispatchQueue.main.async {
                            Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveSet), userInfo: nil, repeats: false)
                        }
                    } else if ckerror.code == CKError.zoneBusy {
                        let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                            DispatchQueue.main.async {
                                Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveSet), userInfo: nil, repeats: false)
                            }
                        } else if ckerror.code == CKError.limitExceeded {
                            let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval
                                DispatchQueue.main.async {
                                    Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveSet), userInfo: nil, repeats: false)
                                }
                            } else if ckerror.code == CKError.notAuthenticated {
                                NotificationCenter.default.post(name: Notification.Name("noCloud"), object: nil, userInfo: nil)
                                } else if ckerror.code == CKError.networkFailure {
                                    NotificationCenter.default.post(name: Notification.Name("networkFailure"), object: nil, userInfo: nil)
                                        } else if ckerror.code == CKError.networkUnavailable {
                                        NotificationCenter.default.post(name: Notification.Name("noWiFi"), object: nil, userInfo: nil)
                                        } else if ckerror.code == CKError.quotaExceeded {
                                            NotificationCenter.default.post(name: Notification.Name("quotaExceeded"), object: nil, userInfo: nil)
                                        } else if ckerror.code == CKError.partialFailure {
                                            NotificationCenter.default.post(name: Notification.Name("partialFailure"), object: nil, userInfo: nil)
                                        } else if (ckerror.code == CKError.internalError || ckerror.code == CKError.serviceUnavailable) {
                                            NotificationCenter.default.post(name: Notification.Name("serviceUnavailable"), object: nil, userInfo: nil)
                                        }
                } // end of guard statement
            return
        }

        if error != nil {
                //print(error!.localizedDescription)
        } else {
                //print("ok")
        }
    }

    saveRecordsOperation.qualityOfService = .background
    privateDB.add(saveRecordsOperation)
    theApp.isNetworkActivityIndicatorVisible = true
}
于 2017-05-08T05:27:33.533 回答