Ich habe an einer Methode gearbeitet, mit der in einer iPhone-Anwendung gespeicherte Kerndaten zwischen mehreren Geräten, z. B. einem iPad oder einem Mac, synchronisiert werden können. Es gibt nicht viele (wenn überhaupt) Synchronisierungs-Frameworks für die Verwendung mit Core Data unter iOS. Ich habe jedoch über folgendes Konzept nachgedacht:
Gibt es etwas Besonderes, über das ich nachdenken muss? Ich habe mir REST Frameworks wie ObjectiveResource , Core Resource und RestfulCoreData angesehen. Natürlich arbeiten alle mit Ruby on Rails, an das ich nicht gebunden bin, aber es ist ein Anfang. Die Hauptanforderungen, die ich an meine Lösung habe, sind:
Ich habe über eine Reihe von Herausforderungen nachgedacht:
Fehlt hier noch etwas? Auf welche Frameworks sollte ich achten, um dies zu ermöglichen?
Ich empfehle, die von Dan Grover auf der iPhone 2009-Konferenz diskutierte Synchronisierungsstrategie sorgfältig zu lesen und umzusetzen. Diese kann hier als PDF-Dokument heruntergeladen werden.
Dies ist eine praktikable Lösung und nicht so schwer zu implementieren (Dan implementierte dies in mehreren seiner Anwendungen), was sich mit der von Chris beschriebenen Lösung überschneidet. Eine eingehende theoretische Diskussion der Synchronisation finden Sie in dem Artikel von Russ Cox (MIT) und William Josephson (Princeton):
Dateisynchronisation mit Vektorzeitpaaren
dies gilt auch für Kerndaten mit einigen offensichtlichen Änderungen. Dies bietet insgesamt eine wesentlich robustere und zuverlässigere Synchronisierungsstrategie, erfordert jedoch mehr Aufwand, um korrekt implementiert zu werden.
BEARBEITEN:
Es scheint, dass die PDF-Datei des Grovers nicht mehr verfügbar ist (defekter Link, März 2015). UPDATE: Der Link ist über die Way Back Machine verfügbar hier
Das von Marcus Zarra entwickelte Objective-C-Framework ZSync ist veraltet, da iCloud anscheinend die korrekte Synchronisation der Kerndaten unterstützt.
Ich habe etwas Ähnliches getan wie Sie. Lassen Sie mich Ihnen sagen, was ich gelernt habe und wie ich es gemacht habe.
Ich gehe davon aus, dass Sie eine Eins-zu-Eins-Beziehung zwischen Ihrem Core Data-Objekt und dem Modell (oder DB-Schema) auf dem Server haben. Sie möchten lediglich den Serverinhalt mit den Clients synchronisieren, Clients können jedoch auch Daten ändern und hinzufügen. Wenn ich das richtig verstanden habe, dann lies weiter.
Ich habe vier Felder hinzugefügt, um die Synchronisierung zu unterstützen:
Fügen Sie auf dem Client Code hinzu, um sync_status für Ihr Modellobjekt auf 1 zu setzen, wenn sich etwas ändert und mit dem Server synchronisiert werden muss. Neue Modellobjekte müssen eine GUID generieren.
Die Synchronisierung ist eine einzelne Anforderung. Die Anfrage enthält:
Der Server erhält die Anfrage und führt dies aus:
Die App erhält die Antwort und führt dies aus:
Ich hoffe das hilft. Ich habe den Word-Datensatz und das Modell austauschbar verwendet, aber ich glaube, Sie haben die Idee. Viel Glück.
Wenn Sie noch auf der Suche nach einer Lösung sind, schauen Sie sich das Couchbase-Handy an. Das macht im Grunde alles, was Sie wollen. ( http://www.couchbase.com/nosql-databases/couchbase-mobile )
Ähnlich wie @Cris habe ich class für die Synchronisation zwischen Client und Server implementiert und alle bisher bekannten Probleme behoben (Senden/Empfangen von Daten zum/vom Server, Zusammenführen von Konflikten basierend auf Zeitstempeln, Entfernen doppelter Einträge unter unzuverlässigen Netzwerkbedingungen, Synchronisieren verschachtelter Daten und Dateien etc ..)
Sie teilen der Klasse einfach mit, welche Entität und welche Spalten synchronisiert werden sollen und wo sich Ihr Server befindet.
M3Synchronization * syncEntity = [[M3Synchronization alloc] initForClass: @"Car"
andContext: context
andServerUrl: kWebsiteUrl
andServerReceiverScriptName: kServerReceiverScript
andServerFetcherScriptName: kServerFetcherScript
ansSyncedTableFields:@[@"licenceNumber", @"manufacturer", @"model"]
andUniqueTableFields:@[@"licenceNumber"]];
syncEntity.delegate = self; // delegate should implement onComplete and onError methods
syncEntity.additionalPostParamsDictionary = ... // add some POST params to authenticate current user
[syncEntity sync];
Quelle, Arbeitsbeispiel und weitere Anweisungen finden Sie hier: github.com/knagode/M3Synchronization .
Ich denke, eine gute Lösung für das Problem GUID ist "verteiltes ID-System". Ich bin mir nicht sicher, wie der richtige Begriff lautet, aber ich denke, das ist, was MS SQL Server-Dokumente verwendet haben, um es aufzurufen ( SQL verwendet/verwendet diese Methode für verteilte/synchronisierte Datenbanken.
Der Server weist alle IDs zu. Bei jeder Synchronisierung wird als Erstes die Option "Wie viele IDs habe ich noch auf diesem Client?" Aktiviert. Wenn der Client zur Neige geht, fragt er den Server nach einem neuen ID-Block. Der Client verwendet dann IDs in diesem Bereich für neue Datensätze. Dies funktioniert für die meisten Anforderungen hervorragend, wenn Sie einen Block zuweisen können, der groß genug ist, dass er vor der nächsten Synchronisierung "nie" ausgeht, aber nicht so groß ist, dass der Server mit der Zeit ausgeht. Sollte der Client einmal zur Neige gehen, kann die Handhabung recht einfach sein. Sagen Sie dem Benutzer einfach "Entschuldigung, Sie können nicht mehr Elemente hinzufügen, bis Sie synchronisieren" Probleme trotzdem?
Ich denke, dies ist der Verwendung von zufälligen GUIDs überlegen, da zufällige GUIDs nicht 100% sicher sind und normalerweise viel länger als eine Standard-ID sein müssen (128-Bit gegenüber 32-Bit). Normalerweise verfügen Sie über Indizes nach ID und behalten ID-Nummern häufig im Speicher. Daher ist es wichtig, diese klein zu halten.
Wollte eigentlich nicht als Antwort posten, aber ich weiß nicht, dass irgendjemand einen Kommentar sehen würde, und ich denke, es ist wichtig für dieses Thema und nicht in anderen Antworten enthalten.
Ich habe gerade die erste Version meiner neuen Core Data Cloud Syncing-API veröffentlicht, die als SynCloud bekannt ist. SynCloud weist viele Unterschiede zu iCloud auf, da es eine Mehrbenutzer-Synchronisierungsoberfläche ermöglicht. Es unterscheidet sich auch von anderen Synchronisierungs-APIs, da es relationale Mehrtabellendaten ermöglicht.
Weitere Informationen finden Sie unter http://www.syncloudapi.com
Mit iOS 6 SDK erstellt, ist es ab dem 27.09.2012 auf dem neuesten Stand.
Benachrichtigen Sie den Benutzer, die Daten per Push-Benachrichtigung zu aktualisieren. Verwenden Sie einen Hintergrund-Thread in der App, um die lokalen Daten und die Daten auf dem Cloud-Server zu überprüfen. Während die Änderung auf dem Server stattfindet, ändern Sie die lokalen Daten und umgekehrt.
Ich denke, der schwierigste Teil ist es, abzuschätzen, auf welcher Seite Daten ungültig sind.
Hoffe das kann dir helfen
Zuerst sollten Sie überlegen, wie viele Daten, Tabellen und Beziehungen Sie haben werden. In meiner Lösung habe ich die Synchronisierung über Dropbox-Dateien implementiert. Ich beobachte Änderungen im Haupt-MOC und speichere diese Daten in Dateien (jede Zeile wird als gzipped json gespeichert). Wenn eine Internetverbindung besteht, überprüfe ich, ob Änderungen an Dropbox vorgenommen wurden (Dropbox gibt mir Delta-Änderungen), lade sie herunter und füge sie zusammen (die letzten Siege) und lege schließlich geänderte Dateien ab. Vor der Synchronisierung sperre ich Dropbox, um zu verhindern, dass andere Clients unvollständige Daten synchronisieren. Beim Herunterladen von Änderungen ist es sicher, dass nur teilweise Daten heruntergeladen werden (z. B. unterbrochene Internetverbindung). Wenn der Download vollständig oder teilweise abgeschlossen ist, werden die Dateien in Core Data geladen. Wenn ungelöste Beziehungen bestehen (nicht alle Dateien werden heruntergeladen), werden die Dateien nicht mehr geladen und der Download wird zu einem späteren Zeitpunkt beendet. Beziehungen werden nur als GUID gespeichert, sodass ich problemlos überprüfen kann, welche Dateien geladen werden müssen, um die vollständige Datenintegrität zu gewährleisten. Die Synchronisierung beginnt, nachdem Änderungen an den Kerndaten vorgenommen wurden. Wenn es keine Änderungen gibt, wird alle paar Minuten und beim Start der App nach Änderungen in Dropbox gesucht. Zusätzlich, wenn Änderungen an den Server gesendet werden, sende ich eine Übertragung an andere Geräte, um sie über Änderungen zu informieren, damit sie schneller synchronisiert werden können. Jede synchronisierte Entität hat die Eigenschaft GUID (guid wird auch als Dateiname für Austauschdateien verwendet). Ich habe auch eine Synchronisierungsdatenbank, in der ich die Dropbox-Revision jeder Datei speichere (ich kann sie vergleichen, wenn Dropbox Delta zurückgesetzt wird) Die Dateien enthalten außerdem den Entitätsnamen, den Status (gelöscht/nicht gelöscht), die GUID (wie der Dateiname), die Datenbankrevision (um Datenmigrationen zu erkennen oder eine Synchronisierung mit nie verwendeten App-Versionen zu vermeiden) und natürlich die Daten (wenn die Zeile gelöscht ist) nicht gelöscht).
Diese Lösung funktioniert für Tausende von Dateien und etwa 30 Entitäten. Anstelle von Dropbox könnte ich den Schlüssel-/Wertspeicher als REST Webdienst verwenden, den ich später ausführen möchte, aber keine Zeit dafür habe :) Im Moment ist meine Lösung meiner Meinung nach zuverlässiger als iCloud und, was sehr wichtig ist, ich habe die volle Kontrolle darüber, wie es funktioniert (hauptsächlich, weil es mein eigener Code ist).
Eine andere Lösung besteht darin, MOC-Änderungen als Transaktionen zu speichern - es werden viel weniger Dateien mit dem Server ausgetauscht, aber es ist schwieriger, das erste Laden in der richtigen Reihenfolge in leere Kerndaten durchzuführen. iCloud funktioniert auf diese Weise, und auch andere Synchronisierungslösungen haben einen ähnlichen Ansatz, z. B. TICoreDataSync .
- AKTUALISIERUNG
Nach einer Weile bin ich zu Ensembles gewechselt - ich empfehle diese Lösung, weil ich das Rad neu erfunden habe.