Ich versuche, eine Core Data-Anwendung für das iPhone zu schreiben, die eine externe Datenquelle verwendet. Ich verwende Core Data nicht wirklich, um meine Objekte zu erhalten, sondern eher für das Objekt-Lebenszyklus-Management. Ich habe eine ziemlich gute Idee, wie ich Core Data für lokale Daten verwenden kann, habe aber ein paar Probleme mit Remote-Daten festgestellt. Ich werde nur die Flickr-API als Beispiel verwenden.
Als erstes muss ich, wenn ich eine Liste der letzten Fotos sagen muss, diese aus einer externen Datenquelle holen. Nachdem ich die Liste abgerufen habe, scheint es, als müsste ich für jedes Foto verwaltete Objekte erstellen und erstellen. An dieser Stelle kann ich in meinem Code fortfahren und das Standard-Core-Data-API verwenden, um eine Abrufanforderung einzurichten und eine Teilmenge von Fotos beispielsweise über Hunde abzurufen.
Aber was, wenn ich dann fortfahren und eine Liste der Fotos des Benutzers abrufen möchte? Da die Möglichkeit besteht, dass sich diese beiden Datensätze überschneiden, muss ich eine Abrufanforderung für die vorhandenen Daten durchführen, die bereits vorhandenen Daten aktualisieren und dann die neuen Objekte einfügen?
-
Im älteren Muster würde ich einfach separate Datenstrukturen für jeden dieser Datensätze haben und auf sie entsprechend zugreifen. Ein recentPhotos-Set und ein userPhotos-Set. Aber da das allgemeine Muster von Core Data darin zu bestehen scheint, einen verwalteten Objektkontext zu verwenden, scheint es (ich könnte falsch liegen), dass ich meine Daten mit dem Hauptdatenpool zusammenführen muss. Aber das scheint eine Menge Overhead zu sein, nur um eine Liste von Fotos zu bekommen. Soll ich einen separaten Kontext für verwaltete Objekte für die verschiedenen Gruppen erstellen? Sollten Core Data überhaupt hier verwendet werden?
Ich finde an Core Data ansprechend, dass ich vorher (für einen Web-Service) bestimmte Daten anfordern und entweder in der Anfrage filtern oder in Code filtern und eine Liste erstellen würde, die ich verwenden würde. Mit Core Data kann ich nur eine Liste von Objekten abrufen, sie zu meinem Pool hinzufügen (nach Bedarf alte Objekte aktualisieren) und dann abfragen. Ein Problem, das ich mit diesem Ansatz jedoch sehen kann, ist, dass wenn Objekte extern gelöscht werden, ich es nicht wissen kann, da ich meine alten Daten behalte.
Bin ich hier weit weg von der Basis? Gibt es Muster, denen Menschen beim Umgang mit Remote-Daten und Core-Daten folgen? :) Ich habe ein paar Posts von Leuten gefunden, die sagen, dass sie es getan haben, und dass es für sie funktioniert, aber wenig in der Art von Beispielen. Danke.
Es scheint mir, dass Ihre ersten Instinkte richtig sind: Sie sollten fetchrequests verwenden, um Ihr bestehendes Geschäft zu aktualisieren. Der Ansatz, den ich für einen Importeur verwendet habe, war der folgende: Erhalte eine Liste aller Dateien, die für den Import geeignet sind, und speichere sie irgendwo. Ich gehe hier davon aus, dass das Abrufen dieser Liste schnell und leicht ist (nur ein Name und eine URL oder eine eindeutige ID), aber das Importieren von etwas wird etwas mehr Zeit und Aufwand erfordern und der Benutzer kann das Programm beenden oder etwas tun sonst bevor alles importiert ist.
Dann, in einem separaten Hintergrund-Thread (das ist nicht so schwer wie es klingt dank NSRunLoop und NSTimer, google auf "Core Data: Effizient Daten importieren"), erhalten Sie das erste Element dieser Liste, das Objekt von Flickr oder wo auch immer und suchen Sie danach in der Core Data-Datenbank (lesen Sie sorgfältig den Prädikat-Programmierleitfaden von Apple zum Einrichten effizienter, zwischengespeicherter NSFetchRequests). Wenn das Remoteobjekt bereits in Core Data vorhanden ist, aktualisieren Sie die Informationen nach Bedarf, falls sie nicht eingefügt werden. Wenn dies erledigt ist, entfernen Sie das Objekt aus der zu importierenden Liste und fahren Sie mit dem nächsten fort.
Für das Problem von Objekten, die im Remote-Speicher gelöscht wurden, gibt es zwei Lösungen: periodische Synchronisierung oder faule, bedarfsgesteuerte Synchronisierung. Bedeutet das Importieren eines Fotos von Flickr das Importieren des Originaldokuments und all seiner Metadaten (ich weiß nicht, was die Richtlinie bezüglich des Eigentums betrifft) oder möchten Sie nur ein Miniaturbild und einige Informationen importieren? Wenn Sie alles lokal speichern, können Sie alle paar Tage oder Wochen eine Überprüfung durchführen, um zu sehen, ob auch alles in Ihrem lokalen Geschäft entfernt vorhanden ist: Wenn nicht, kann der Benutzer das Foto trotzdem behalten oder löschen. Wenn Sie nur Thumbnails oder Vorschaubilder speichern, müssen Sie sich jedes Mal mit Flickr verbinden, wenn der Benutzer das vollständige Bild sehen möchte. Wenn es gelöscht wurde, können Sie den Benutzer informieren und lokal löschen oder als nicht mehr erreichbar markieren.
Sie könnten eine Kombination aus zwei Dingen versuchen. Diese Strategie wird Ihnen eine Schnittstelle geben, wo Sie die Ergebnisse eines NSFetchRequest zweimal erhalten: Einmal synchron, und noch einmal, wenn Daten aus dem Netzwerk geladen wurden.
Erstellen Sie Ihre eigene Unterklasse von
NSFetchRequest
, die eine zusätzliche Blockeigenschaft annimmt
Ausführen, wenn der Abruf beendet ist.
Dies ist für Ihre asynchrone
Anfrage an das Netzwerk. Lass uns anrufen
es FLRFetchRequest
Erstellen Sie eine Klasse, an die Sie übergeben werden
diese Anfrage. Nennen wir es
%Code%. FLRPhotoManager
hat eine Methode FLRPhotoManager
, die annimmt
Instanz von executeFetchRequest:
und ...
Dies ist das beste Muster, das ich mir ausgedacht habe, aber wie du bin ich an den Meinungen anderer interessiert.
In einer solchen Situation könnten Sie die Archivierungsfunktionen von Cocoa verwenden, um die Fotoobjekte (und einen Index) zwischen den Sitzungen auf der Festplatte zu speichern und sie bei jedem Aufruf der App an Flickr einfach zu überschreiben.
Aber da Sie bereits Core Data verwenden und die Funktionen, die es bietet, nicht modifizieren, ändern Sie Ihr Datenmodell so, dass es ein "source" - oder "callType" -Attribut enthält. Im Moment erstellen Sie implizit eine Reihe von Objekten mit der Source "Flickr API", aber Sie können die verschiedenen API-Aufrufe ebenso einfach als eindeutige Quellen behandeln und diese dann explizit speichern.
Um mit dem Löschen umzugehen, wäre der einfachste Weg, den Datenspeicher bei jeder Aktualisierung zu löschen. Andernfalls müssten Sie über alles iterieren und nur die Fotoobjekte mit Dateinamen löschen, die nicht in den neuen Ergebnissen enthalten waren.
Ich plane, etwas Ähnliches selbst zu machen, also hoffe ich, dass das hilft.
PS: Wenn Sie die Fotoobjekte nicht zwischen Sitzungen speichern, können Sie einfach zwei verschiedene Kontexte verwenden und diese separat abfragen. Solange sie nicht gespeichert werden und der zentrale Speicher bereits nichts enthält, funktioniert es genau so, wie du es beschrieben hast.
Tags und Links iphone core-data web-services cocoa-design-patterns