Technologische Neuigkeiten, Bewertungen und Tipps!

Erste Schritte mit der Realm-Datenbank in Swift

Hinweis: Der folgende Artikel hilft Ihnen weiter: Erste Schritte mit der Realm-Datenbank in Swift

Zurück zum Blog

Realm ist ein benutzerfreundliches Datenbank-Framework für iOS und Swift. In diesem Tutorial erfahren Sie, wie Sie mit Realm Database in Ihren eigenen iOS-App-Projekten beginnen.

Wir besprechen, wie Realm funktioniert, wie Sie es in Ihren iOS-Projekten zum Speichern und Abrufen von Daten verwenden können und wie sich Realm von den herkömmlicheren Datenbanktools für iOS unterscheidet.

Realm ist ein Kraftpaket, wenn es um die Verwaltung von Datenbanken geht, und wie Sie sehen werden, lässt es sich bequem zusammen mit Swift verwenden. Es ist eine besonders gute Wahl für reine lokale Datenbanken, obwohl die Realm-Plattform alles bietet, was Sie von einem synchronisierten, cloudbasierten Dienst benötigen.

Bevor wir Swift-Code schreiben, besprechen wir, was Realm Database ist. Realm ist eine Datenbankbibliothek (und Plattform) für iOS, Android und das Web. Es ist eine überzeugende Alternative zu SQLite und Core Data – Tools, die häufig in der praktischen iOS-Entwicklung verwendet werden.

Realm verfügt über drei verschiedene Produkte:

  • Realm Database ist ein lokales Datenbank-Framework (Open Source)
  • Realm Platform ist ein Offline-First-Cloud-Datenbankdienst (30 $/m)
  • Realm Studio ist ein Verwaltungstool für Realm Database und Realm Platform

Dieses Tutorial konzentriert sich ausschließlich auf die Open-Source-Realm-Datenbank, obwohl der hier besprochene Code auch mit Realm Platform verwendet werden kann.

Realm ist eine Datenbank, sodass Sie sie zum strukturierten Speichern und Abrufen von Datenobjekten in Ihrer iOS-App verwenden können. Die Datenbank bleibt zwischen App-Starts bestehen und eignet sich daher perfekt für die langfristige Objektspeicherung.

Ein paar Beispiele:

  • Sie können Realm zum Zwischenspeichern von Nachrichtenartikeldaten verwenden, sodass der Benutzer Ihrer App die neuesten Nachrichten offline und unterwegs lesen kann
  • Sie können damit gespeicherte Spieldaten in Ihrer iOS-Spiele-App speichern und die Daten laden, damit ein Benutzer dort weiterspielen kann, wo er aufgehört hat
  • Sie können Realm verwenden, um Textnotizen und deren Eigenschaften, wie z. B. den Titel der Notiz und den Zeitpunkt ihrer Erstellung, in einer Datenbank zu speichern

Am einfachsten ist es, eine Datenbank mit einer Tabellenkalkulation wie der folgenden zu vergleichen. Die Zeilen der Tabelle entsprechen einzelnen Einträgen in der Datenbank, die als Objekte bezeichnet werden, und die Spalten der Tabelle beschreiben Eigenschaften dieser Objekte.

Wir können die obige Struktur mit einer Swift-Klasse wie folgt beschreiben:

Klasse Benutzer {
Var-ID:Int
var Benutzername:String
var highscore:Int
}

Eine Datenbank kann viele Instanzen der oben genannten Benutzerklasse enthalten, genau wie die oben genannte Tabelle vier Dateneinträge enthält.

Das Interessante und Praktische an Realm ist, dass Sie mit Datenbankobjekten wie tatsächlichen Swift-Objekten arbeiten können. Im Gegensatz zu Core Data, SQLite und Firebase müssen Sie keine von der Datenbank zurückgegebenen Objekte oder Zeilen den Swift-Objekten „zuordnen“. Realm erledigt das für Sie – Sie können einfach ein Swift-Objekt in einer Realm-Datenbank ablegen, und wenn Sie Objekte abfragen, erhalten Sie sofort dieselbe Klasse zurück.

Die Installation von Realm in Ihrem Projekt ist unkompliziert. Die vollständigen Anweisungen finden Sie in der Realm-Dokumentation. Hier ist die Kurzversion:

  1. Installieren Sie CocoaPods auf Ihrem Mac mit sudo gem install Cocoapods
  2. Führen Sie das Pod-Repo-Update aus, um die neuesten Spezifikationen von CocoaPods zu erhalten
  3. Fügen Sie Ihrem Projekt eine Poddatei und den Pod „RealmSwift“ hinzu.
  4. Gehen Sie im Terminal zu Ihrem Projektverzeichnis und führen Sie pod install aus
  5. Öffnen Sie die .xcworkspace-Datei in Xcode, um mit der Arbeit an Ihrem Projekt fortzufahren

Jetzt schreiben wir echten Swift-Code!

Realm-Datenmodelle sind nichts anderes als reguläre Swift-Klassen mit regulären Eigenschaften. In unserer hypothetischen App werden wir Notizen mit der folgenden Klasse speichern:

Klasse Note {
Var-ID = 0
var title = „“
var erstellt = Date()
var text = „“
}

Die obige Klasse definiert 4 Eigenschaften. Jede Eigenschaft hat einen Standardwert und die Typen dieser Eigenschaften werden von Swift abgeleitet (Int, String, Date, String).

So erstellen Sie eine Instanz von Note Klasse:

Beachten Sie = Note()
note.id = 1
note.title = „Einkaufsliste“
note.text = „Milch, Butter, Kuchen, Äpfel“

Das Note Die Klasse kann nicht sofort mit Realm verwendet werden, daher müssen wir sie ein wenig ändern. So was:

Klasse Note: Objekt {
@objc dynamische Var-ID = 0
@objc dynamischer Var-Titel = „“
@objc dynamische Variable erstellt = Date()
@objc dynamischer var text = „“
}

Folgendes hat sich geändert:

  • Der Note Die Klasse ist nun eine Unterklasse der Object-Klasse, die Teil der RealmSwift-Bibliothek ist. Diese Unterklasse enthält den Code, der für die Arbeit mit Realm erforderlich ist.
  • Jede Eigenschaft, die wir in Realm speichern möchten, muss diese @objc- und dynamischen Attribute direkt vor var erhalten. Dadurch wird sichergestellt, dass das zugrunde liegende Realm-Framework auf die Eigenschaften zugreifen kann.

Wenn Sie direkt mit den Klassen der Realm-Bibliothek arbeiten, vergessen Sie nicht, RealmSwift oben in Ihre Swift-Datei zu importieren!

In den meisten Datenbankumgebungen möchten Sie auch Objekte eindeutig identifizieren. Woher wissen Sie, ob zwei Note Instanzen beziehen sich auf dieselben zugrunde liegenden Daten? In unserer Hypothese Note In der Klasse verwenden wir die Eigenschafts-ID, um jeder Notiz eine eindeutige Kennung zu geben. Wenn die ID-Eigenschaft von zwei ist Note Da die Objekte identisch sind, verweisen sie auf dasselbe Realm-Datenbankobjekt. Auf diese Weise können wir sie aktualisieren, ändern oder überschreiben.

Realm muss wissen, welche Eigenschaft wir als eindeutige Kennung verwenden möchten. Wir könnten die ID, aber auch den Titel und sogar das Erstellungsdatum der Notiz verwenden. So teilen wir dies Realm mit:

Klasse Note: Objekt {

statische Funktion PrimaryKey() überschreiben -> String? {
„id“ zurückgeben
}
}

Die Funktion „primaryKey()“ wird hinzugefügt Note Klasse und wird von der Implementierung ihrer Superklasse überschrieben. Das einzige, was wir innerhalb der Funktion tun, ist die Rückgabe einer Zeichenfolge „id“, die den Namen der Eigenschaft enthält, die ein Realm-Datenobjekt eindeutig identifiziert.

OK, jetzt wo das Note Das Datenmodell ist vorhanden – wir können endlich Dinge in Realm speichern und abrufen!

Datenmodelle in Realm können viel komplexer werden, mit Optionen, Arrays mit Liste, benutzerdefinierten Gettern und Settern, Indizes, ignorierten Eigenschaften und komplexen Datentypen. Das meiste davon ist direkt in Ihrem Datenmodell konfiguriert! Weitere Informationen hierzu finden Sie in der Realm-Dokumentation.

Das Schreiben von Daten in eine Realm-Datenbank ist unkompliziert:

  1. Rufen Sie einen Verweis auf eine Realm-Instanz ab
  2. Fügen Sie die Objekte, die Sie speichern möchten, einer Schreibtransaktion hinzu
  3. Übernehmen Sie die Schreibtransaktion in die Datenbank

Lassen Sie uns die hier implizierten Prinzipien besprechen. Wir haben Datenmodelle bereits im vorherigen Abschnitt besprochen. Die Realm-Umgebung hat eine weitere wichtige Komponente, den Realm selbst.

Technisch gesehen ist ein Realm eine Instanz eines Realm Mobile Database-Containers. In Wirklichkeit handelt es sich um eine .realm-Datei, die Datenbankobjekte speichert. Es ist am einfachsten, einen Realm als „die Datenbank“ zu betrachten.

Eine App verfügt über einen Standardbereich, und Sie können nach Bedarf weitere Bereiche erstellen. Realms können auch mit der cloudbasierten Realm-Plattform synchronisiert werden. Wir werden einfach den standardmäßigen lokalen Realm verwenden.

Bevor Sie aus der Datenbank lesen oder in sie schreiben können, müssen Sie einen Verweis auf eine Realm-Instanz erhalten. Hier ist wie:

versuchen {
let realm = versuche Realm()
} fangen {
print(error.localizedDescription)
}

Im obigen Snippet instanziiert der Code let realm = try Realm() den Standard-Realm und weist ihn der Realm-Konstante zu. Wir verwenden außerdem die Swift-Fehlerbehandlung, um eventuell auftretende Fehler abzufangen.

Es ist hier erwähnenswert, dass …

  • … die Instanziierung eines Realms kann Fehler auslösen, wenn die Ressourcen eingeschränkt sind, z. Das iPhone hat nicht mehr genügend Arbeitsspeicher oder Speicherplatz
  • … zur Laufzeit wird nur die erste Realm()-Instanz Fehler auslösen, falls vorhanden, da nachfolgende Zugriffe auf diesen Realm zwischengespeichert werden und immer erfolgreich sind
  • … also ist es wichtig, dass Sie Ihre App so entwerfen, dass Sie Fehler beheben können, die bei jedem ersten Realm()-Aufruf auftreten, und gleichzeitig mit try! Fehler aus dem Weg räumen. oder Versuche?

In Realm muss jede Änderung an der Datenbank in einer sogenannten Schreibtransaktion erfolgen. Dazu gehören neu erstellte oder hinzugefügte Objekte, Aktualisierungen von Objekten und Löschungen.

Eine Schreibtransaktion bündelt alle Änderungen an der Datenbank, sodass sie auf einmal nacheinander in Realm geschrieben werden können. Da das Schreiben in die Datenbank ein blockierender, synchronisierter Vorgang ist, ist es effizienter, alle Änderungen auf einmal vorzunehmen. Sie sollten auch darauf abzielen, die Anzahl der Schreibtransaktionen zu minimieren, d. h. so viele wie möglich zu stapeln.

Nehmen wir an, Ihr App-Benutzer hat eine Notiz in der App erstellt und möchte diese speichern. Wir definieren das folgende Notizobjekt:

Beachten Sie = Note()
note.id = 2
note.title = „Denken Sie an die Milch!“
note.text = „Mama fragte, ob ich einen Liter Milch mit nach Hause bringen könnte.“

Wie zuvor erhalten wir einen Verweis auf den Standard-Realm:

let realm = versuchen! Reich()

Schließlich fügen wir das Notizobjekt in einer Schreibtransaktion zu Realm hinzu:

versuchen! realm.write {
realm.add(Anmerkung)
}

Folgendes passiert:

  • Der Funktionsaufruf add(…) ist in einen realm.write { … }-Block eingeschlossen. Dieser Block kapselt die Schreibtransaktion, dh alles, was in diesem Block hinzugefügt, geändert oder gelöscht wird, wird als Teil der Transaktion in Realm geschrieben. (Note dass es sich technisch gesehen um einen nachgestellten Abschluss handelt!)
  • Der Versuch! Die Anweisung deaktiviert die Fehlerbehandlung aus Bequemlichkeitsgründen, Sie sollten jedoch immer einen vernünftigen Ansatz zur Fehlerbehandlung verfolgen. Wenn die Schreibtransaktion aufgrund von Fehlern fehlschlägt und Sie try! verwendet haben, stürzt Ihre App ab.
  • Der realm.add(note)-Code fügt das Notizobjekt zu Realm hinzu. Dieses Objekt wird nun in der Realm-Datenbank gespeichert und wir können es später aus der Datenbank zurückholen (siehe nächster Abschnitt).

Was ist, wenn Sie mehrere Objekte zu Realm hinzufügen möchten? All das können Sie innerhalb des write { … }-Blocks tun, aber in manchen Szenarien ist das unmöglich.

Schauen Sie sich das an:

realm.beginWrite()

für Text in Notizen
{
Beachten Sie = Note()
note.text = Text

realm.add(Anmerkung)
}

versuchen! realm.commitWrite()

Im obigen Code durchlaufen wir ein Array von Zeichenfolgen, die als „Notizen“ bezeichnet werden, und fügen jede der Zeichenfolgen zu a hinzu Note Objekt und Speichern dieses Objekts in Realm.

Wir können hier keinen write { … }-Block verwenden, deshalb öffnen wir die Schreibtransaktion mit realm.beginWrite(). Anschließend wird jedes Objekt hinzugefügt, und sobald dies erledigt ist, schreiben wir die Transaktion mit realm.commitWrite() fest.

Das Arbeiten mit einer Schreibtransaktion auf diese Weise „öffnet“ effektiv die Tore für die neuen Objekte, markiert dann die Transaktion als abgeschlossen, woraufhin die Daten in die Datenbank geschrieben werden.

Bedenken Sie, dass das Öffnen und Schließen der Transaktion ausgeglichen sein muss, das heißt, Sie sollten beginWrite() nicht aufrufen, ohne irgendwann auch commitWrite() aufzurufen.

Das Aktualisieren und Löschen von Objekten funktioniert auf die gleiche Weise. Bedenken Sie, dass wir die Texteigenschaft eines zuvor gespeicherten Notizobjekts ändern und diese Änderung in der Datenbank speichern möchten. Hier ist wie:

versuchen! realm.write {
note.text = „Mama hat gefragt, bring zwei Gallonen Milch mit!“
}

Ebenso können Objekte auch aus der Realm-Datenbank gelöscht werden:

versuchen! realm.write {
realm.delete(Hinweis)
}

Eindrucksvoll! Lassen Sie uns fortfahren und besprechen, wie Sie Objekte aus Realm abrufen können.

Stellen Sie sich vor, der Benutzer Ihrer App hat 10 Notizen in der App erstellt. Alle diese Notizen werden in der Realm-Datenbank gespeichert. Sie möchten diese Notizen in einer Tabellenansicht anzeigen. Wie rufen Sie die ab? Note Objekte aus Realm?

Das Abrufen von Daten aus Realm erfolgt mit einer Abfrage. Eine Abfrage kapselt im Wesentlichen die Informationen, die zum Abrufen von Objekten erforderlich sind. Ein paar Beispiele:

  • Nimm alle Note Objekte
  • Holen Sie sich die Notizen von vor 7 Tagen bis jetzt
  • Holen Sie sich die Notizen, die das Wort „Lebensmittel“ enthalten.

Um alle Notizen von Realm zu erhalten, gehen wir einfach wie folgt vor:

let Notes = realm.objects(Note.selbst)

Dies weist Realm an, alle Objekte dieses Typs abzurufen Noteund weisen Sie sie der Notizensammlung zu. Anschließend können wir die Notizensammlung iterieren, um alle Titel der Notizen anzuzeigen.

Das Durchlaufen der Sammlung ist so einfach wie:

für Notizen in Notizen
{
print(note.text)
}

Hier gilt es einige Dinge zu beachten. Erstens ist die Art der Notizen „Ergebnisse“. Dies ist ein generischer Sammlungstyp von Realm. Es funktioniert ähnlich wie ein Array, d. h. Sie können die Elemente der Sammlung iterieren, aber es gibt noch mehr:

  • Eine Ergebnissammlung verweist direkt auf die Daten in der Datenbank. Die Daten werden nicht kopiert und Änderungen an den Daten (in einer Schreibtransaktion) werden sofort in die Datenbank zurückgespiegelt.
  • Die Ergebnissammlung wird automatisch aktualisiert. Wenn also ein anderer Teil Ihrer App (derselbe Thread) die Daten in demselben Ergebnissatz ändert, werden diese Änderungen sofort angezeigt. Dies vermeidet eine Menge Konflikte.
  • Die Sammlungselemente in den Ergebnissen sind verzögert, d. h. wenn Sie Tausende von Objekten abfragen, werden diese Objekte nur dann geladen, wenn auf sie zugegriffen wird. Auch Abfragen werden zurückgestellt; Sie werden bei Bedarf ausgeführt, sodass Sie komplexe Abfragen sicher verketten können, ohne sich Gedanken über die Zwischenausführung machen zu müssen.

Das Abfragen von Realm-Objekten und das Arbeiten mit Ergebnissen ist leistungsstark und wird von nun an komplexer. Ein paar andere Dinge, die Realm tun kann, sind:

  • Ergebnismengen mit der Funktion filter(_:) filtern. Dies funktioniert genauso wie NSPredicate, sodass Sie Objekte basierend auf einer Vielzahl von Parametern filtern und abfragen können.
  • Das Sortieren von Ergebnismengen erfolgt mit den Funktionen sorted(_:) und sorted(byKeyPath:ascending:). Mit SortDescriptor-Objekten können Sie sogar nach mehreren Eigenschaften sortieren.
  • Sie können Abfragen mit geringem Aufwand „verketten“. Dadurch können Sie beispielsweise zunächst Notizen aus einem bestimmten Zeitraum abfragen und dann Notizen auswählen, die einen bestimmten Suchbegriff enthalten.
  • Im Gegensatz zu SQL-basierten Abfragen müssen Sie Abfragen in Realm nicht einschränken. Da die Ergebnisse verzögert sind, rufen Sie nur Daten ab, auf die Sie tatsächlich zugreifen. Dies bedeutet, dass Sie keine großen Ergebnismengen paginieren müssen und dass Sie nichts weiter tun müssen, um mit UITableView einen unendlichen Bildlauf zu ermöglichen.
  • Realm kann natürlich Beziehungen aufbauen! Das Framework ist vollständig relational, sodass Sie Eins-zu-Eins-, Viele-zu-Eins- und Viele-zu-Viele-Beziehungen zwischen Objekten erstellen können. Und was wirklich cool ist, ist, dass Sie Swift-Objekte in Beziehungen direkt referenzieren und Listensammlungen problemlos durchlaufen können.
  • Realm unterstützt Migrationsvorgänge, also das Aktualisieren der Datenbank einer vorhandenen App zur Laufzeit. Sie können auch .realm-Datenbanken mit Ihrer App bündeln, um eine Datenbank mit tatsächlichen Daten hinzuzufügen, wenn ein Benutzer Ihre App herunterlädt.

Wir haben gerade erst an der Oberfläche dessen gekratzt, was Realm leisten kann – es kann noch viel, viel mehr. Vor allem, wenn man die cloudbasierte Realm-Plattform und den Offline-First-Synchronisierungsansatz von Realms bedenkt.

Was Realm so überzeugend macht, ist der geringe syntaktische Aufwand beim Umgang mit der Datenbank selbst. Objekte, die Sie in der Datenbank speichern, sind nur Instanzen der Swift-Klasse, und was Sie zurückerhalten, sind dieselben Objekte. Sauber!

Table of Contents