Ich bin gerade dabei, ein Brainstorming für eine Cloud-Synchronisierungslösung für eine Core Data-Anwendung durchzuführen, die ich derzeit entwickle. Ich plane, den Code dafür als Open Source zu veröffentlichen, sobald er fertig ist, damit jeder ihn mit seinen Core Data-Apps verwenden kann.) Hier ist, was ich denke:
Server-Seite
Anbieter von Speicherplatz
Wie bei allen Cloud-Synchronisationssystemen ist die Speicherung ein wichtiger Teil des Puzzles. Es gibt viele Möglichkeiten, dies zu handhaben. Ich könnte meinen eigenen Server für die Speicherung einrichten oder einen Dienst wie Amazon S3 nutzen, aber da ich im Moment mit 0 $ Kapital anfange, ist eine bezahlte Speicherlösung keine praktikable Option. Nach einiger Überlegung habe ich mich für folgende Lösung entschieden Dropbox (ein bereits gut etablierter Anbieter von Cloud-Synchronisierungsanwendungen und -Speicher). Die Vorteile der Verwendung von Dropbox sind:
- Es ist kostenlos (für eine begrenzte Menge an Speicherplatz)
- Neben dem Speicherdienst übernimmt er auch die Synchronisierung mit der Cloud.
- Kürzlich wurde ein Objective-C SDK veröffentlicht, das die Verwendung in Mac- und iPhone-Anwendungen erheblich erleichtert.
Für den Fall, dass ich mich entschließe, in Zukunft zu einem anderen Speicheranbieter zu wechseln, beabsichtige ich, diesem Cloud-Sync-Framework "Dienste" hinzuzufügen, die es im Grunde jedem ermöglichen, eine Dienstklasse zu erstellen, die eine Schnittstelle zu einem Speicheranbieter seiner Wahl bildet und die dann einfach in das Framework eingefügt werden kann.
Struktur der Lagerung
Dies ist ein wirklich schwieriger Teil, um herauszufinden, so brauche ich so viel Input wie ich kann hier. 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 zu dieser Struktur:
- Der Hauptordner "CloudSyncFramework" (Name unbestimmt) wird separate Ordner für jede Anwendung enthalten, die das Framework verwendet
- Jeder Anwendungsordner enthält eine Geräte Ordner und ein Einrichtungen Ordner
- En Geräte enthält einen Ordner für jedes Gerät, das für das Konto registriert ist. Der Geräteordner wird nach der Geräte-ID benannt, die Sie etwa wie folgt erhalten
[[UIDevice currentDevice] uniqueIdentifier]
(unter iOS) oder eine Seriennummer (unter Mac OS). - Jeder Geräteordner enthält zwei Dateien: geräteinfo y Änderungssatz . geräteinfo enthält Informationen über das Gerät (z. B. Betriebssystemversion, Datum der letzten Synchronisierung, Modell usw.) und die Änderungssatz Datei enthält Informationen über Objekte, die seit der letzten Synchronisierung des Geräts geändert wurden. Beide Dateien sind einfache NSDictionaries, die in Dateien mit
NSKeyedArchiver
. - Jede Kerndateneinheit hat einen Unterordner unter dem Einrichtungen Ordner
- Unter jedem Entitätsordner wird für jedes Objekt, das zu dieser Entität gehört, eine eigene Datei angelegt. Diese Datei enthält ein JSON-Wörterbuch mit den Schlüssel-Werte-Paaren.
Gleichzeitige Synchronisierung
Dies ist einer der Bereiche, in denen ich fast völlig ahnungslos bin. Wie kann ich 2 Geräte gleichzeitig mit der Cloud verbinden und synchronisieren? Hier besteht ein hohes Risiko, dass Dinge nicht mehr synchronisiert werden oder sogar Daten beschädigt werden.
Handhabung von Migrationen
Wieder einmal ein weiteres Gebiet, das keine Ahnung hat. Wie würde ich Migrationen des von Core Data verwalteten Objektmodells handhaben? Am einfachsten scheint es zu sein, den Cloud-Datenspeicher zu löschen und eine neue Kopie der Daten von einem Gerät hochzuladen, das den Migrationsprozess durchlaufen hat, aber das scheint etwas riskant zu sein, und vielleicht gibt es einen besseren Weg.
Kunden-Seite
Konvertierung von NSManagedObjects in JSON
Das Konvertieren von Attributen in JSON ist keine sehr schwierige Aufgabe (es gibt jede Menge Code dafür im Web). Beziehungen sind hier das Hauptproblem. In ce Stackoverflow-Beitrag stellt Marcus Zarra einen Code vor, in dem die Beziehungsobjekte selbst dem JSON-Wörterbuch hinzugefügt werden. Er erwähnt jedoch, dass dies je nach der Struktur des Modells zu einer Endlosschleife führen kann, und ich bin 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, um eine ID als Zeichenfolge für eine NSManagedObject
. Dann könnte ich Beziehungen in JSON als ein Array von IDs speichern. Am ehesten habe ich folgende Lösung gefunden [[managedObject objectID] URIRepresentation]
, aber das ist nicht wirklich eine ID für ein Objekt, seine mehr von einem Speicherort für das Objekt in den persistenten Speicher, und ich weiß nicht, ob seine konkret genug, um als Referenz für ein Objekt zu verwenden.
Ich nehme an, ich könnte eine UUID-Zeichenfolge für jedes Objekt generieren und sie als Attribut speichern, aber ich bin offen für Vorschläge.
Synchronisierung von Änderungen in der Cloud
Die erste (und immer noch beste) Lösung, die mir dafür in den Sinn kam, war das Hören auf die NSManagedObjectContextObjectsDidChangeNotification
um eine Liste der geänderten Objekte zu erhalten und diese Objekte dann im Cloud-Datenspeicher zu aktualisieren/löschen/einzufügen. Nachdem die Änderungen gespeichert wurden, müsste ich die Änderungssatz Datei für jedes andere registrierte Gerät, um die neu geänderten Objekte wiederzugeben.
Ein Problem, das sich hier stellt, ist, Wie gehe ich mit einer fehlgeschlagenen oder unterbrochenen Synchronisierung um? . Eine Idee, die ich habe, ist, die Änderungen zunächst in ein temporäres Verzeichnis in der Cloud zu verschieben und dann, sobald dies als erfolgreich bestätigt wurde, mit den Stammdaten in der Cloud zusammenzuführen, damit eine Unterbrechung in der Mitte der Synchronisierung die Daten nicht beschädigt. Dann würde ich Aufzeichnungen der Objekte, die in der Cloud aktualisiert werden müssen, in einer plist-Datei oder ähnlichem speichern, die bei der nächsten Internetverbindung der App übertragen wird.
Abrufen von geänderten Objekten
Dies ist recht einfach, das Gerät lädt seine Änderungssatz Datei, findet heraus, welche Objekte aktualisiert/eingefügt/gelöscht werden müssen, und handelt dann entsprechend.
Und damit sind meine Gedanken zur Logik, die dieses System verwenden wird, zusammengefasst :-) Jede Einsicht, jeder Vorschlag, jede Antwort auf ein Problem usw. ist willkommen. sehr gewürdigt.
アップデイト
Nach langem Nachdenken und der Lektüre von TechZens Vorschlägen habe ich einige Änderungen an meinem Konzept vorgenommen.
Die größte Änderung, die ich mir ausgedacht habe, ist, dass jedes Gerät eine getrennt Datenspeicher in der Cloud. Grundsätzlich gilt, dass jedes Mal, wenn der verwaltete Objektkontext spart (danke TechZen), werden die Änderungen in den Datenspeicher des Geräts hochgeladen. Nachdem diese Änderungen aktualisiert wurden, wird eine "Changeset"-Datei mit den Änderungsdetails erstellt und in den Changeset-Ordnern der ANDEREN Geräte, die die Anwendung verwenden, gespeichert. Wenn die anderen Geräte eine Verbindung zur Synchronisierung herstellen, durchsuchen sie den Änderungssatzordner und wenden jeden Änderungssatz auf den lokalen Datenspeicher an, um dann ihre jeweiligen Datenspeicher in der Cloud ebenfalls zu aktualisieren.
Wenn nun ein neues Gerät für das Konto registriert wird, findet es die neueste Kopie der Daten von allen Geräten und laden Sie diese herunter, um sie als lokalen Speicher zu verwenden. Dies löst das Problem der gleichzeitigen Synchronisierung und verringert die Gefahr der Datenverfälschung, da es keinen "zentralen" Datenspeicher gibt, sondern jedes Gerät nur seine Daten berührt und Änderungen aktualisiert, anstatt dass jedes Gerät gleichzeitig auf dieselben Daten zugreift und sie verändert.
Es gibt einige offensichtliche Konfliktsituationen, die es zu lösen gilt, vor allem in Bezug auf das Löschen von Objekten. Wenn ein Änderungssatz heruntergeladen wird, der die Anwendung anweist, ein Objekt zu löschen, das gerade bearbeitet wird, usw., muss es Möglichkeiten geben, damit umzugehen.