Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Mobile Development

Kerndaten von Grund auf neu: Verwaltete Objekte und Abrufanforderungen

by
Read Time:14 minsLanguages:
This post is part of a series called Core Data from Scratch.
Core Data from Scratch: Data Model
Core Data from Scratch: Relationships and More Fetching

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

Nachdem Sie alles über Cora Data-Datenmodelle noch im Kopf haben, ist es an der Zeit, mit Core Data zu arbeiten. In diesem Artikel lernen wir NSManagedObject kennen, die Klasse, mit der Sie am meisten interagieren, wenn Sie mit Core Data arbeiten. Sie lernen, wie Sie Datensätze erstellen, lesen, aktualisieren und löschen.

Sie werden auch einige andere Core Data-Klassen kennenlernen, z. B. NSFetchRequest und NSEntityDescription. Lassen Sie mich zunächst NSManagedObject vorstellen, Ihren neuen besten Freund.

1. Verwaltete Objekte

Instanzen von NSManagedObject stellen einen Datensatz im Backing Store von Core Data dar. Denken Sie daran, es spielt keine Rolle, wie dieser Hintergrundspeicher aussieht. Um die Datenbankanalogie erneut zu überprüfen, enthält eine NSManagedObject-Instanz jedoch die Informationen einer Zeile in einer Datenbanktabelle.

Der Grund, warum Core Data NSManagedObject anstelle von NSObject als Basisklasse für die Modellierung von Datensätzen verwendet, wird etwas später sinnvoller. Bevor wir mit NSManagedObject arbeiten, müssen wir einige Dinge über diese Klasse wissen.

NSEntityDescription

Jede NSManagedObject-Instanz ist einer Instanz von NSEntityDescription zugeordnet. Die Entitätsbeschreibung enthält Informationen zum verwalteten Objekt, z. B. die Entität des verwalteten Objekts sowie deren Attribute und Beziehungen.

NSManagedObjectContext

Ein verwaltetes Objekt ist auch mit einer Instanz von NSManagedObjectContext verknüpft. Der verwaltete Objektkontext, zu dem ein verwaltetes Objekt gehört, überwacht das verwaltete Objekt auf Änderungen.

2. Erstellen eines Datensatzes

Vor diesem Hintergrund ist das Erstellen eines verwalteten Objekts ziemlich einfach. Um sicherzustellen, dass ein verwaltetes Objekt ordnungsgemäß konfiguriert ist, wird empfohlen, den angegebenen Initialisierer zum Erstellen neuer NSManagedObject-Instanzen zu verwenden. Lassen Sie uns sehen, wie das funktioniert, indem Sie ein neues Personenobjekt erstellen.

Öffnen Sie das Projekt aus dem vorherigen Artikel oder klonen Sie es von GitHub. Da wir in diesem Artikel keine funktionale Anwendung erstellen, erledigen wir den größten Teil unserer Arbeit in der Anwendungsdelegatenklasse TSPAppDelegate. Öffnen Sie TSPAppDelegate.m und aktualisieren Sie die Implementierung der application:didFinishLaunchingWithOptions: wie unten gezeigt.

Als erstes erstellen wir eine Instanz der NSEntityDescription-Klasse, indem wir entityForName:inManagedObjectContext: aufrufen. Wir übergeben den Namen der Entität, für die wir ein verwaltetes Objekt erstellen möchten, @"Person" und eine NSManagedObjectContext-Instanz.

Warum müssen wir ein NSManagedObjectContext-Objekt übergeben? Wir geben den Namen an, für den wir ein verwaltetes Objekt erstellen möchten, müssen aber auch Core Data mitteilen, wo sich das Datenmodell für diese Entität befindet. Denken Sie daran, dass ein verwalteter Objektkontext an einen persistenten Geschäftskoordinator gebunden ist und ein persistenter Geschäftskoordinator einen Verweis auf ein Datenmodell enthält. Wenn wir einen verwalteten Objektkontext übergeben, fragt Core Data seinen persistenten Speicherkoordinator nach seinem Datenmodell, um die gesuchte Entität zu finden.

Im zweiten Schritt rufen wir den festgelegten Initialisierer der NSManagedObject-Klasse initWithEntity:insertIntoManagedObjectContext: auf. Wir übergeben die Entitätsbeschreibung und eine NSManagedObjectContext-Instanz. Warten? Warum müssen wir eine andere NSManagedObjectContext-Instanz übergeben? Denken Sie daran, was ich früher geschrieben habe. Ein verwaltetes Objekt ist einer Entitätsbeschreibung zugeordnet und befindet sich in einem verwalteten Objektkontext. Aus diesem Grund teilen wir Core Data mit, mit welchem verwalteten Objektkontext das neue verwaltete Objekt verknüpft werden soll.

Das ist nicht zu komplex, oder? Wir haben jetzt ein neues Personenobjekt erstellt. Wie ändern wir seine Attribute oder definieren eine Beziehung? Dies erfolgt durch Nutzung der Schlüsselwertcodierung. Um den Vornamen des soeben erstellten neuen Personenobjekts zu ändern, gehen Sie wie folgt vor.

Wenn Sie mit der Codierung von Schlüsselwerten vertraut sind, sollte dies sehr vertraut aussehen. Da die NSManagedObject-Klasse die Schlüsselwertcodierung unterstützt, ändern wir ein Attribut, indem wir setValue:forKey: aufrufen. So einfach ist das.

Ein Nachteil dieses Ansatzes ist die Leichtigkeit, mit der Sie Fehler einführen können, indem Sie ein Attribut oder einen Beziehungsnamen falsch schreiben. Außerdem werden Attributnamen von Xcode nicht automatisch vervollständigt, wie dies beispielsweise bei Eigenschaftsnamen der Fall ist. Wir können dieses Problem beheben, aber das werden wir uns etwas später in dieser Serie ansehen.

Bevor wir mit NSManagedObject fortfahren, setzen wir das age von newPerson auf 44.

Wenn Sie mit der Schlüsselwertcodierung nicht vertraut sind, werden Sie überrascht sein, dass wir anstelle einer Ganzzahl, wie wir sie in unserem Datenmodell definiert haben, ein NSNumber-Literal übergeben haben. Die Methode setValue:forKey: akzeptiert nur Objekte, keine Grundelemente. Denken Sie daran.

3. Speichern eines Datensatzes

Obwohl wir jetzt eine neue Personeninstanz haben, hat Core Data die Person noch nicht in ihrem Backing Store gespeichert. Das von uns erstellte verwaltete Objekt befindet sich derzeit in dem verwalteten Objektkontext, in den es eingefügt wurde. Um das Personenobjekt im Sicherungsspeicher zu speichern, müssen Sie die Änderungen des verwalteten Objektkontexts speichern, indem Sie save: on it aufrufen.

Die Methode save: gibt einen Booleschen Wert zurück, um das Ergebnis der Sicherungsoperation anzuzeigen, und akzeptiert einen Zeiger auf ein NSerror-Objekt, der uns mitteilt, was schief gelaufen ist, wenn die Sicherungsoperation nicht erfolgreich war. Schauen Sie sich zur Verdeutlichung den folgenden Codeblock an.

Erstellen Sie die Anwendung und führen Sie sie aus, um festzustellen, ob alles wie erwartet funktioniert. Sind Sie auch auf einen Absturz gestoßen? Was hat Ihnen die Konsolenausgabe gesagt? Sieht es ähnlich aus, wie die Ausgabe unten?

Xcode sagt uns, dass es eine NSDate-Instanz für das first Attribut erwartet hat, aber wir haben einen NSString übergeben. Wenn Sie das im vorherigen Artikel erstellte Kerndatenmodell öffnen, werden Sie feststellen, dass der Typ des first-Attributs tatsächlich Date ist. Ändern Sie es in String und führen Sie die Anwendung noch einmal aus.

Noch ein Absturz? Obwohl dies ein fortgeschritteneres Thema ist, ist es wichtig zu verstehen, was los ist.

Datenmodellkompatibilität

Die Ausgabe in der Xcode-Konsole sollte der unten gezeigten Ausgabe ähneln. Beachten Sie, dass sich der Fehler vom vorherigen unterscheidet. Xcode teilt uns mit, dass das Modell zum Öffnen des Geschäfts nicht mit dem Modell zum Erstellen des Geschäfts kompatibel ist. Wie ist es passiert?

Als wir die Anwendung vor einigen Augenblicken zum ersten Mal starteten, überprüfte Core Data das Datenmodell und erstellte basierend auf diesem Modell einen Speicher für uns, in diesem Fall eine SQLite-Datenbank. Core Data ist jedoch clever. Es stellt sicher, dass die Struktur des Sicherungsspeichers und die des Datenmodells kompatibel sind. Dies ist wichtig, um sicherzustellen, dass wir aus dem Backing Store zurückbekommen, was wir erwarten und was wir dort überhaupt platzieren.

Beim ersten Absturz haben wir festgestellt, dass unser Datenmodell einen Fehler enthält, und wir haben den Typ des first-Attributs von Date in String geändert. Mit anderen Worten, wir haben das Datenmodell geändert, obwohl Core Data den Sicherungsspeicher basierend auf dem falschen Datenmodell bereits für uns erstellt hat.

Nach der Aktualisierung des Datenmodells haben wir die Anwendung erneut gestartet und sind auf den zweiten Absturz gestoßen. Beim Erstellen des Core Data-Stacks stellt Core Data unter anderem sicher, dass das Datenmodell und der Sicherungsspeicher (sofern vorhanden) kompatibel sind. Dies war in unserem Beispiel nicht der Fall, daher der Absturz.

Wie lösen wir das? Die einfache Lösung besteht darin, die Anwendung vom Gerät oder vom iOS-Simulator zu entfernen und die Anwendung erneut zu starten. Dies können Sie jedoch nicht tun, wenn Sie bereits eine Anwendung im App Store haben, die von anderen Personen verwendet wird. In diesem Fall verwenden Sie Migrationen. Dies wird in einem zukünftigen Artikel erläutert.

Da unsere Anwendung nicht von Millionen Benutzern verwendet wird, können wir die Anwendung sicher von unserem Testgerät entfernen und erneut ausführen. Wenn alles gut gegangen ist, wird die neue Person jetzt sicher im Geschäft gespeichert, die für uns erstellte SQLite-Datenbank Core Data.

Inspektion des Backing Store

Sie können überprüfen, ob der Speichervorgang funktioniert, indem Sie einen Blick in die SQLite-Datenbank werfen. Wenn Sie die Anwendung im iOS-Simulator ausgeführt haben, navigieren Sie zu ~/<USER>/Library/Application Support/iPhone Simulator/<VERSION>/<OS>/Applications/<ID>/Documents/Core_Data.sqlite Um Ihnen das Leben zu erleichtern, empfehle ich Ihnen, SimPholders zu installieren, ein Tool, das das Navigieren zum oben genannten Pfad erheblich erleichtert. Öffnen Sie die SQLite-Datenbank und überprüfen Sie die Tabelle mit dem Namen ZPERSON. Die Tabelle sollte einen Eintrag haben, den wir vor einer Minute eingefügt haben.

Sie sollten zwei Dinge beachten. Erstens muss die Datenbankstruktur nicht verstanden werden. Core Data verwaltet den Backing Store für uns und wir müssen seine Struktur nicht verstehen, um mit Core Data arbeiten zu können. Zweitens, greifen Sie niemals direkt auf das Geschäft zu. Core Data ist für den Backing Store verantwortlich, und wir müssen dies respektieren, wenn wir möchten, dass Core Data seine Arbeit gut macht. Wenn wir mit der SQLite-Datenbank oder einem anderen Geschäft interagieren, gibt es keine Garantie dafür, dass Core Data weiterhin ordnungsgemäß funktioniert. Kurz gesagt, Core Data ist für das Geschäft verantwortlich. Lassen Sie es also in Ruhe.

4. Datensätze abrufen

Obwohl wir uns NSFetchRequest im nächsten Artikel genauer ansehen werden, benötigen wir die NSFetchRequest-Klasse, um Core Data nach Informationen aus dem von ihr verwalteten Objektdiagramm zu fragen. Mal sehen, wie wir den zuvor eingefügten Datensatz mit NSFetchRequest abrufen können.

Nach dem Initialisieren der Abrufanforderung erstellen wir ein NSEntityDescription-Objekt und weisen es der entity -Eigenschaft der Abrufanforderung zu. Wie Sie sehen können, verwenden wir die NSEntityDescription-Klasse, um Core Data mitzuteilen, an welcher Entität wir interessiert sind.

Das Abrufen von Daten wird von der NSManagedObjectContext-Klasse behandelt. Wir rufen executeFetchRequest:error: auf und übergeben die Abrufanforderung und einen Zeiger auf ein NSError-Objekt. Die Methode gibt ein Array von Ergebnissen zurück, wenn die Abrufanforderung erfolgreich ist, und nil, wenn ein Problem auftritt. Beachten Sie, dass Core Data immer ein NSArray-Objekt zurückgibt, wenn die Abrufanforderung erfolgreich ist, selbst wenn wir ein Ergebnis erwarten oder wenn Core Data keine übereinstimmenden Datensätze gefunden hat.

Führen Sie die Anwendung aus und überprüfen Sie die Ausgabe in der Xcode-Konsole. Unten sehen Sie, was zurückgegeben wurde, ein Array mit einem Objekt vom Typ NSManagedObject. Die Entität des Objekts ist Person.

Um auf die Attribute des Datensatzes zuzugreifen, verwenden wir wie zuvor die Schlüsselwertcodierung. Es ist wichtig, sich mit der Schlüsselwertcodierung vertraut zu machen, wenn Sie mit Core Data arbeiten möchten.

Sie fragen sich möglicherweise, warum ich das person -Objekt vor und nach der Protokollierung des person namens protokolliere. Dies ist tatsächlich eine der wichtigsten Lektionen dieses Artikels. Schauen Sie sich die Ausgabe unten an.

Wenn wir das person -Objekt zum ersten Mal in der Konsole protokollieren, werden angezeigt data: <fault>. Beim zweiten Mal enthalten data jedoch den Inhalt der Attribute und Beziehungen des Objekts. Warum das? Dies hat alles mit Fehlern zu tun, einem Schlüsselkonzept von Core Data.

5. Fehler

Das Konzept, das dem Fehler zugrunde liegt, gilt nicht nur für Core Data. Wenn Sie jemals mit Active Record in Ruby on Rails gearbeitet haben, wird das Folgende sicherlich eine Glocke läuten. Das Konzept ist nicht identisch, aber aus Entwicklersicht ähnlich.

Core Data versucht, seinen Speicherbedarf so gering wie möglich zu halten, und eine der Strategien, mit denen dies erreicht wird, ist ein Fehler. Als wir vor einem Moment die Datensätze für die Person-Entität abgerufen haben, hat Core Data die Abrufanforderung ausgeführt, die verwalteten Objekte, die die abgerufenen Datensätze darstellen, jedoch nicht vollständig initialisiert.

Was wir zurückbekommen haben, ist ein Fehler, ein Platzhalterobjekt, das den Datensatz darstellt. Das Objekt ist vom Typ NSManagedObject und wir können es als solches behandeln. Durch die nicht vollständige Initialisierung des Datensatzes wird der Speicherbedarf von Core Data gering gehalten. In unserem Beispiel ist dies keine signifikante Speicherersparnis, aber stellen Sie sich vor, was passieren würde, wenn wir Dutzende, Hunderte oder sogar Tausende von Datensätzen abrufen würden.

Fehler sind im Allgemeinen nichts, worüber Sie sich Sorgen machen müssen. Sobald Sie auf ein Attribut oder eine Beziehung eines verwalteten Objekts zugreifen, wird der Fehler ausgelöst. Dies bedeutet, dass Core Data den Fehler in ein realisiertes verwaltetes Objekt umwandelt. Sie können dies in unserem Beispiel sehen und das ist auch der Grund, warum die zweite Protokollanweisung des person objekts keinen Fehler an die Konsole druckt.

Fehler sind etwas, das viele Neulinge auslöst, und ich möchte daher sicherstellen, dass Sie die Grundlagen dieses Konzepts verstehen. Wir werden später in dieser Serie mehr über Fehler erfahren.

6. Aktualisieren von Datensätzen

Das Aktualisieren von Datensätzen ist genauso einfach wie das Erstellen eines neuen Datensatzes. Sie rufen den Datensatz ab, ändern ein Attribut oder eine Beziehung und speichern den Kontext des verwalteten Objekts. Die Idee ist dieselbe wie beim Erstellen eines Datensatzes. Da das verwaltete Objekt, der Datensatz, mit einem verwalteten Objektkontext verknüpft ist, sind diesem Änderungen, Einfügungen und Aktualisierungen bekannt. Wenn der Kontext des verwalteten Objekts gespeichert wird, wird alles von Core Data an den Sicherungsspeicher weitergegeben.

Schauen Sie sich den folgenden Codeblock an, in dem wir den abgerufenen Datensatz aktualisieren, indem wir das Alter der Person ändern und die Änderungen speichern.

Sie können überprüfen, ob das Update erfolgreich war, indem Sie den SQLite-Speicher wie zuvor erneut betrachten.

7. Datensätze löschen

Das Löschen eines Datensatzes erfolgt nach dem gleichen Muster wie das Erstellen und Aktualisieren von Datensätzen. Wir teilen dem Kontext des verwalteten Objekts mit, dass ein Datensatz aus dem persistenten Speicher gelöscht werden muss, indem wir deleteObject: aufrufen und das verwaltete Objekt übergeben, das gelöscht werden soll.

Löschen Sie in unserem Projekt das zuvor abgerufene Personenobjekt, indem Sie es an die deleteObject:-Methode des verwalteten Objektkontexts übergeben. Beachten Sie, dass der Löschvorgang erst in den Sicherungsspeicher übernommen wird, wenn Sie save: im Kontext des verwalteten Objekts aufrufen.

Abschluss

In diesem Tutorial haben wir viel mehr behandelt als nur das Erstellung, Abruf, Aktualisierung und Löschen von Datensätzen. Wir haben einige wichtige Konzepte angesprochen, auf die sich Core Data stützt, z. B. Fehler und Datenmodellkompatibilität.

In der nächsten Folge dieser Serie erfahren Sie, wie Sie Beziehungen erstellen und aktualisieren. Wir werden uns die NSFetchRequest-Klasse genauer ansehen. Wir werden auch NSPredicate und NSSortDescriptor verwenden, um unsere Abrufanforderungen flexibel, dynamisch und leistungsstark zu gestalten.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.