2014-07-01 7 views
7

Ich habe CloudKit getestet, da ich eine App veröffentlichen möchte, wenn iOS8 veröffentlicht wird. Es scheint einfach genug, um Daten mit dem folgenden Code zu speichern:Modifizierte Daten in CloudKit speichern

und ich erhalte keine Fehler von diesem. Allerdings, wenn ich versuchen Sie es erneut um den Code auszuführen, vielleicht, weil ich den Rekordwert zu

[record setValue:@"newValue" forKey:@"defaultKey"]; 

geändert haben erhalte ich einen Fehler, der die Frage aufwirft, wie gehe ich über ein modifiziertes Stück Daten zu speichern. Schließlich ist dies ein grundlegender Beitrag zum Speichern von Daten in der Cloud. Der Fehler ist unten und jede Hilfe würde sehr geschätzt werden, zögern Sie nicht, nach weiteren Informationen zu fragen. Dieser Fehler

Error: <CKError 0x17024afb0: "Server Record Changed" (14/2017); "Error saving record <CKRecordID: 0x144684a80; basicRecord:(_defaultZone:__defaultOwner__)> to server: (null)"; uuid = 182C497F-966C-418A-9E6A-5563BA6CC6CD; container ID = "iCloud.com.yourcompany.CloudKit"> 

Antwort

11

ist wahrscheinlich, weil saveRecord: funktioniert nur für neue Datensätze oder Datensätze, die auf dem Server neuer ist als die Version sind:

Diese Methode speichert die Aufzeichnung nur, wenn es zuvor gespeichert wurde nie oder wenn es neuer als die Version auf dem Server ist. Sie können diese Methode nicht verwenden, um neuere Versionen eines Datensatzes auf dem Server zu überschreiben. CKDatabase docs

Der empfohlene Ansatz einen vorhandenen Datensatz (oder einen Satz von Datensätzen) zu ändern, um eine CKModifyRecordsOperation Satz mit dem gewünschten savePolicy zu verwenden ist mit Konflikten umgehen:

Nachdem die Felder eines Datensatzes ändern, Verwenden Sie diese Art von Operationsobjekt, um diese Änderungen in einer Datenbank zu speichern. (...) Beim Speichern von Datensätzen bestimmt der Wert in der savePolicy-Eigenschaft, wie bei Konflikten auf dem Server verfahren wird. CKModifyRecordsOperation docs

1

Aus der Dokumentation von CKRecord:

Neue Datensätze existieren nur im Speicher, bis Sie sie explizit zu iCloud speichern.

Wenn Sie den neuen Wert [record setValue:@"newValue" forKey:@"defaultKey"]; setzen, haben Sie den Datensatz bereits gespeichert, wodurch er ungültig wird.

Sie können CKModifyRecordsOperation verwenden und in den meisten Situationen ist es vielleicht vorzuziehen, aber Sie müssen nicht. Holen Sie einfach Ihre Daten mit einem neuen CKRecord, und führen Sie diesen Datensatz dann in saveRecord: wie beschrieben here.

0

Nachdem Sie den Datensatz speichern, es zu holen, so dass der retured Datensatz wird dann die RecordID haben, dass Wolkenjunge

Dann auf demselben geholt Datensatz, verwenden setValue die Daten, die Sie

ändern möchten ändern hinzugefügt dann sind Sie CFModifyRecordsOperation im Beispiel unten verwenden können, enthält cachedCKRecordsServiceCenter die abgerufenen Datensätze aus und Wolkenjunge die Datensätze haben die Wolkenjunge RecordID die in ihnen ......

  //find this service center in the cached records 
      for (_,serviceCenter) in (theModel?.cachedCKRecordsServiceCenter.enumerated())! //is data for logged in Co ONLY with NO Co name attached 
      { 
       let name = serviceCenter["name"] as! String 
       returnValue = "Try Again" 
       if name == displayedRecordName 
       { 
        serviceCenter.setValue(displayedRecordName! + "_" + (theModel?.companyName)!, forKey: "name") //db values have Co name appended 
        serviceCenter.setValue(label2Text.text, forKey:"street1") 
        serviceCenter.setValue(label3Text.text, forKey:"street2") 
        serviceCenter.setValue(label4Text.text, forKey:"city") 
        serviceCenter.setValue(label5Text.text, forKey:"state") 
        serviceCenter.setValue(label6Text.text, forKey:"zip") 
        serviceCenter.setValue(label7Text.text, forKey:"phone") 
        serviceCenter.setValue(label8Text.text, forKey:"email") 
        serviceCenter.setValue(label9Text.text, forKey:"note") 

        let saveRecordsOperation = CKModifyRecordsOperation() 

        var ckRecordsArray = [CKRecord]() 
        // set values to ckRecordsArray 
        ckRecordsArray.append(serviceCenter) 

        saveRecordsOperation.recordsToSave = ckRecordsArray 
        saveRecordsOperation.savePolicy = .ifServerRecordUnchanged 

        appDelegate.locked = true 
        saveRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in 
         if error != nil { 
          // Really important to handle this here 
          ////////print("ERROR: Unable to update Driver Location: Error= \(error)") 
          self.returnValue = "ERROR: Unable to update Driver Location: ERROR = \(error)" 
          self.appDelegate.locked=false 
         } 
         else 
         { 
          ////print("Successfully updated Service Center") 
          self.appDelegate.locked=false 
          self.returnValue = "Successfully updated Service Center" 
          self.appDelegate.locked=false 

          //reget the data into the cach 
          self.theModel?.fetchServiceCenterFromCloudKit1() 
         } 

        } 

        CKContainer.default().publicCloudDatabase.add(saveRecordsOperation) 
       } 
      }