Ich versuche einige Datensatzänderungen mit CloudKit hochzuladen. Ich bin dabei, eine CKModifyRecordsOperation zu verwenden, um einen Batch-Upload von Datensätzen durchzuführen, die sich auf dem Gerät geändert haben. Die Datensätze befinden sich alle in einer benutzerdefinierten Zone.
Aus irgendeinem Grund kommt die Operation immer wieder mit einem Fehler zurück, der mir sagt: "Die Schutzdaten stimmen nicht überein"
Hier ist der Code:
%Vor%Hier ist der Fehler, den es mir gibt:
%Vor% Was genau ist in Ihrem self.localChanges
-Array? CKRecord
Ich nehme an, aber sind die geänderten Datensätze, die Sie hochladen, auf denselben CKRecord-Objekten basiert, die Sie von CloudKit heruntergeladen haben?
Ich hatte eine ähnliche (wenn auch nicht exakte) Fehlermeldung, als ich versuchte, ein frisch zugewiesenes CKRecord mit meinen lokalen Änderungen hochzuladen und erwartete, dass es die Kopie des Servers überschreiben würde. Ich habe es behoben, indem ich die Remote-Kopie meines Objekts heruntergeladen habe, Updates für die CKRecord-Instanz, die ich von CloudKit erhalten habe, übernommen und dann hochgeladen habe.
Wenn Sie savePolicy
von CKRecordSaveIfServerRecordUnchanged
verwenden, müssen Sie eine entfernte CKRecord
vorab holen (und diese bestimmte Instanz aktualisieren), bevor CKModifyRecordsOperation
. Wenn Sie eine "lokale" CKRecord
zuweisen und sie über CKRecordID
mit einer übereinstimmenden initWithRecordName:
referenzieren, kann CloudKit ein entferntes Änderungs-Tag nicht mit einem (fehlenden) lokalen Änderungs-Tag vergleichen, sodass es mit% co_de fehlschlägt % und die etwas vage Fehlermeldung: "Schutzdaten stimmen nicht überein".
Wenn jedoch ein entfernter CKErrorServerRecordChanged
überhaupt nicht existiert, hat sich der Server-Datensatz sicher nicht geändert und der Speichervorgang kann fortgesetzt werden. Dieses Verhalten ist die Grundlage für den Anwendungsfall "Save If Not Exists" (SQL: INSERT über einen PRIMARY KEY). Wenn Sie eine "lokale" CKRecord
zuweisen und die CKRecord
von savePolicy
verwenden, wird INSERT, aber niemals UPDATE.
Wenn Sie die CKRecordSaveIfServerRecordUnchanged
von savePolicy
und die CKRecordSaveAllKeys
CKRecordZoneID
von ownerName
verwenden, sollten Sie in der Lage sein, (SQL: UPDATE, mit INSERT falls erforderlich) durch ein "lokal" zugeordnet CKOwnerDefaultName
, Speichern eines (Pre-Fetch) Trips über das Netzwerk.
Der Anwendungsfall "Save If Exists" (SQL: UPDATE über einen PRIMARY KEY) kann wahrscheinlich nicht ohne einen (Verifikations-) Trip über das Netzwerk durchgeführt werden.
Ein Haken: Es ist nicht möglich, sowohl eine CKRecord
INSERT als auch eine CKRecordSaveIfServerRecordUnchanged
UPDATE in eine atomare Transaktion zu rollen, da CloudKit Transaktionen nur eine einzige CKRecordSaveAllKeys
über mehrere CKModifyRecordsOperation
/ CKRecord
Instanzen umfassen . Philosophisch gesehen sollte eine "Transaktion" mehrere "Operationen" (SQL: Abfragen) umfassen können, nicht nur mehrere "Datensätze" (SQL: Zeilen).
Es ist erwähnenswert, dass die Lösung dafür zweifach war. Ich habe auch versucht, eine benutzerdefinierte Zone zu verwenden. Wo auch immer ich eine CKRecordZoneID initialisiert habe, sah der Code so aus:
%Vor%Das hätte so aussehen sollen
%Vor%Ich glaube, dass dies ein Teil dessen ist, was die "Schutzdaten, die nicht dem Fehler entsprechen" verursacht hat, aber die Antwort von Dave Teare war auch notwendig, um es zu beheben.
Tags und Links objective-c ios icloud cloudkit