2017-05-08 4 views
0

私は「好きなボタン」を持っていて、すべてのユーザーが同じボタンを使用しています。クラウドコンテナのlikeレコードの値を1つインクリメントするか、1つ減らします。最新バージョンのレコードに更新が行われることをどうすれば保証できますか? Swift 3のコードは、すべてのユーザーが同じレコードの最終値を取得し、他のユーザーが同じレコードを同じ操作で送信している間にインクリメントを適用することを保証できるコードは何ですか?申し訳ありませんが、これについて表示するコードはありません。複数のユーザーが同時にCloudKitレコードの1つを重複することなく更新できるようにするにはどうすればいいですか?

私は約CKErrorServerRecordChangedを読んでいますが、構文でどのように使用するのか分かりません。あなたがコードの例があれば、それは素晴らしいでしょう。

Firebaseで見つかりました。トランザクションと呼ばれ、最後のバージョンに操作を適用するまでレコードバージョンを追跡して、そのレコードを対象とするユーザー操作を失うことはありません。

答えて

1

これはcut'n'pasteの回答ではありませんが、あなたには作業するテンプレートが用意されています。これは、大量のエラーコードの処理を示しています。たとえば、リトライの横にあるアクションは、保存アクションで表示されます。あなたは、このコードでやりたいことをする方法を理解することができます。

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 
} 
関連する問題