Core Data Cloud Sync - brauche Hilfe bei der Logik

Ich bin gerade dabei, eine Cloud-Synchronisierungslösung für eine Core Data-App zu entwickeln, die ich gerade entwickle. Ich plane, den Code dafür als Open-Source-Version zu veröffentlichen, damit jeder ihn mit seinen Core Data-Apps verwenden kann. Daher wird es von der Community sehr geschätzt, wie dieses System funktionieren soll :-) Hier ist, was ich denke:

Server Side

Storage Provider

Wie bei allen Cloud-Synchronisationssystemen ist der Speicher ein wichtiger Teil des Puzzles. Es gibt viele Möglichkeiten, damit umzugehen. Ich könnte meinen eigenen Server für die Speicherung einrichten oder einen Dienst wie Amazon S3 verwenden. Da ich jedoch mit 0 US-Dollar anfange, ist eine kostenpflichtige Speicherlösung derzeit keine praktikable Option. Nach einigem Überlegen entschied ich mich mit @ zu begnüg Dropbox (ein bereits etablierter Anbieter von Cloud-Synchronisierungsanwendungen und -Speichern). Die Vorteile von Dropbox sind:

Es ist kostenlos (für eine begrenzte Menge an Speicherplatz) Es ist nicht nur ein Speicherdienst, sondern verwaltet auch die Cloud-SynchronisierungThey hat kürzlich ein Objective-C SDK veröffentlicht, das die Verwendung in Mac- und iPhone-Apps erheblich vereinfacht.

Wenn ich mich in Zukunft für einen Wechsel zu einem anderen Speicheranbieter entscheide, möchte ich diesem Cloud-Synchronisierungsframework "Dienste" hinzufügen, sodass im Grunde jeder eine Serviceklasse erstellen kann, die an den Speicheranbieter seiner Wahl angepasst werden kann in das Framework eingesteckt werden.

Storage Structure

Das ist ein wirklich schwieriger Teil, also brauche ich so viel Input wie möglich. Ich habe über eine Struktur wie diese nachgedacht:

CloudSyncFramework
======> [app name]
==========> devices
=============> (device id)
================> deviceinfo
================> changeset
==========> entities
=============> (entity name)
================> (object id)

Eine kurze Erklärung dieser Struktur:

Der Master-Ordner "CloudSyncFramework" (Name nicht festgelegt) enthält separate Ordner für jede App, die das Framework @ verwendeeder App-Ordner enthält ein devices Ordner und ein entity MappDas deviceser Ordner @ enthält einen Ordner für jedes Gerät, das mit dem Konto registriert ist. Der Geräteordner wird nach der Geräte-ID benannt, die Sie mit @ erhalten habe[[UIDevice currentDevice] uniqueIdentifier] (unter iOS) oder eine Seriennummer (unter Mac OS).Jeder Geräteordner enthält zwei Dateien:Geräteinformatione und changeset. Geräteinformatione enthält Informationen zum Gerät (z. B. Betriebssystemversion, Datum der letzten Synchronisierung, Modell usw.) und das changeset -Datei enthält Informationen zu Objekten, die sich seit der letzten Synchronisierung des Geräts geändert haben. Beide Dateien sind einfache NSDictionaries, die mit @ in Dateien archiviert werdeNSKeyedArchiver.ede Core Data-Entität hat einen Unterordner unter dem entity MappUnter jedem Entitätsordner hat jedes Objekt, das zu dieser Entität gehört, eine separate Datei. Diese Datei enthält ein JSON-Wörterbuch mit den Schlüssel-Wert-Paaren.

Gleichzeitige Synchronisierung

Dies ist einer der Bereiche, in denen ich fast völlig ahnungslos bin.Wie gehe ich mit 2 Geräten um, die gleichzeitig eine Verbindung zur Cloud herstellen und mit dieser synchronisieren? Anscheinend besteht hier ein hohes Risiko, dass Dinge nicht mehr synchronisiert werden oder sogar Daten beschädigt werden.

Handhabung von Migrationen

Once wieder eine andere ahnungslose Gegend hier.Wie gehe ich mit Migrationen des verwalteten Core Data-Objektmodells um? Am einfachsten ist es, den Cloud-Datenspeicher zu bereinigen und eine neue Kopie der Daten von einem Gerät hochzuladen, das den Migrationsprozess durchlaufen hat. Dies scheint jedoch etwas riskant zu sein, und es gibt möglicherweise einen besseren Weg.

Client Side

Umwandeln von NSManagedObjects in JSON

Die Konvertierung von Attributen in JSON ist keine sehr schwierige Aufgabe (es gibt viel Code im Web). Beziehungen sind hier das Hauptproblem. ImDie stackoverflow post, Marcus Zarra gibt Code bekannt, in dem die Beziehungsobjekte selbst zum JSON-Wörterbuch hinzugefügt werden. Er erwähnt jedoch, dass dies abhängig von der Struktur des Modells zu einer Endlosschleife führen kann, und ich bin mir nicht sicher, ob dies mit meiner Methode funktionieren würde, da ich jedes Objekt als einzelne Datei speichere.

Ich habe versucht, einen Weg zu finden, eine ID als Zeichenfolge für ein @ zu erhalteNSManagedObject. Dann könnte ich Beziehungen in JSON als Array von IDs speichern. Das nächste, was ich gefunden habe, war[[managedObject objectID] URIRepresentation], aber dies ist nicht wirklich eine ID für ein Objekt, sondern eher ein Ort für das Objekt im permanenten Speicher, und ich weiß nicht, ob es konkret genug ist, um als Referenz für ein Objekt verwendet zu werden.

ch nehme an, ich könnte eine UUID-Zeichenfolge für jedes Objekt generieren und als Attribut speichern, bin aber offen für Vorschläg

Synchronisieren von Änderungen in der Cloud

ie erste (und immer noch beste) Lösung, die mir dazu in den Sinn kam, war, auf das @ zu höreNSManagedObjectContextObjectsDidChangeNotification, um eine Liste der geänderten Objekte abzurufen, und aktualisieren / löschen / fügen Sie diese Objekte in den Cloud-Datenspeicher ein. Nachdem die Änderungen gespeichert wurden, müsste ich das @ aktualisier changeset -Datei für jedes andere registrierte Gerät, um die neu geänderten Objekte wiederzugeben.

Ein Problem, das hier auftaucht, ist,wie würde ich mit einer fehlgeschlagenen oder unterbrochenen Synchronisierung umgehen?. Eine Idee, die ich habe, besteht darin, zuerst Änderungen in ein temporäres Verzeichnis in der Cloud zu verschieben und dann, sobald dies als erfolgreich bestätigt wurde, diese mit den Stammdaten in der Cloud zusammenzuführen, damit eine Unterbrechung in der Mitte der Synchronisierung nicht beschädigt wird Daten. Dann würde ich Aufzeichnungen der Objekte, die in der Cloud aktualisiert werden müssen, in einer Plist-Datei oder so etwas speichern, um sie beim nächsten Mal, wenn die App mit dem Internet verbunden ist, zu pushen.

Geänderte Objekte abrufen

Dies ist ziemlich einfach, das Gerät lädt seine changeset file ermittelt, welche Objekte aktualisiert / eingefügt / gelöscht werden müssen, und verhält sich dann entsprechend.

Und das sind meine Gedanken zu der Logik, die dieses System verwenden wird :-) Alle Einsichten, Vorschläge, Antworten auf Probleme usw. sindseh geschätzt.

AKTUALISIERE

Nach langem Überlegen und Lesen von TechZens-Vorschlägen habe ich einige Änderungen an meinem Konzept vorgenommen.

Die größte Änderung, die ich mir ausgedacht habe, ist, jedes Gerät mit einem @ zu versehetrenne Datenspeicher in der Cloud. Grundsätzlich wird jedes Mal der verwaltete Objektkontext speichert (danke TechZen), werden die Änderungen in den Datenspeicher des Geräts hochgeladen. Nachdem diese Änderungen aktualisiert wurden, wird eine "Changeset" -Datei mit Änderungsdetails erstellt und in den Changeset-Ordnern der ANDEREN Geräte gespeichert, die die Anwendung verwenden. Wenn die anderen Geräte eine Verbindung zur Synchronisierung herstellen, durchsuchen sie den Ordner "changeset" und wenden jeden Änderungssatz auf den lokalen Datenspeicher an. Aktualisieren Sie dann auch ihre jeweiligen Datenspeicher in der Cloud.

Now, wenn ein neues Gerät mit dem Konto registriert ist, findet es dasneuest Kopie der Daten von allen Geräten und Herunterladen der Daten zur Verwendung als lokaler Speicher. Dies löst das Problem der gleichzeitigen Synchronisierung und verringert das Risiko von Datenbeschädigungen, da es keinen "zentralen" Datenspeicher gibt, jedes Gerät nur seine Daten berührt und nur Änderungen aktualisiert, anstatt dass jedes Gerät gleichzeitig auf dieselben Daten zugreift und diese ändert.

Es gibt einige offensichtliche Konfliktsituationen, die hauptsächlich im Zusammenhang mit dem Löschen von Objekten zu bewältigen sind. Wenn ein Änderungssatz heruntergeladen wird und die App anweist, ein Objekt zu löschen, das gerade bearbeitet wird, usw., muss es Möglichkeiten geben, damit umzugehen.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage