如何让多个用户同时更新我的​​一条 CloudKit 记录而不重叠?

Posted

技术标签:

【中文标题】如何让多个用户同时更新我的​​一条 CloudKit 记录而不重叠?【英文标题】:How to let multiple users update one of my CloudKit records at the same time without overlapping? 【发布时间】:2017-05-08 00:37:10 【问题描述】:

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

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

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

【问题讨论】:

【参考方案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

【讨论】:

以上是关于如何让多个用户同时更新我的​​一条 CloudKit 记录而不重叠?的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的 nodejs 应用程序为多个用户服务?

在访问中将数据插入多个表的最佳方法?

如何在应用程序中同时处理多个用户请求

电商网站秒杀和抢购的高并发技术实现和优化

多用户同时处理同一条数据解决办法

多个存储过程如何同时更新同一行?