Realm Database Guide – Erstellen einer Notiz-App in Swift für iOS

Wenn Sie Videos gegenüber schriftlichen Artikeln bevorzugen, ist dieser Artikel eine schriftliche Version eines von mir produzierten Videos. Der Inhalt ist identisch.

Dieses Video ist das erste in einer Reihe, die Ihnen hoffentlich zeigt, wie Sie iOS-Frameworks und -Tools wie Siri Shortcuts, CloudKit und mehr nutzen können. Wenn Sie ein bestimmtes Framework oder eine Funktion haben, die Sie gerne in dieser Serie behandelt sehen würden, schreiben Sie mir an jordanosterbergshadowsystemstech oder auf Twitter @josterbe1.

Inhaltsverzeichnis

  1. Einführung
  2. Installation von Abhängigkeiten
  3. Das Modell
  4. Implementierung von Realm
  5. Abschluss

Werfen wir doch einfach mal einen Blick auf die Anwendung, die wir in dieser Serie bauen werden….

Einführung

Die Liste der Notizen in der Anwendung
Einzelne Notizen bearbeiten

Wir haben unsere Liste von Notizen, und wenn wir eine antippen, können wir sie lesen und bearbeiten oder löschen. Ziemlich einfach. Wenn Sie das Startprojekt herunterladen, werden Sie feststellen, dass die Notizen nicht bestehen bleiben, wenn Sie den NoteDetailController beim Tippen auf die Notiz „Apple Park Visit“ öffnen und schließen. Das heißt, der Inhalt der Notiz wird nicht gespeichert, wenn Sie sie bearbeiten.

Das werden wir in diesem Artikel mit Hilfe der Realm-Datenbank herausfinden. Ich verwende Realm seit etwa zwei Jahren und finde, dass seine Einfachheit die Kosten für die Verwendung einer Bibliothek eines Drittanbieters aufwiegt. Tatsächlich verwende ich sie in der App, mit der ich die meiste Zeit meiner persönlichen Entwicklung verbringe (siehe https://countdowns.download), sowohl auf macOS als auch auf iOS.

Installieren von Abhängigkeiten

Um Realm verwenden zu können, müssen wir es mit CocoaPods installieren. CocoaPods ist ein Tool zur Verwaltung von Abhängigkeiten, das in der iOS-Welt weit verbreitet ist, falls Sie es nicht kennen. Wenn Sie CocoaPods nicht bereits auf Ihrem Mac installiert haben, können Sie den Befehl sudo gem install cocoapods verwenden, um loszulegen. Öffnen Sie nun den Projektordner und ein Terminal-Fenster in diesem Verzeichnis.

Geben Sie pod init und dann open Podfile ein.

In die neu erstellte „Poddatei“ müssen wir einen Text schreiben, der CocoaPods mitteilt, welche Bibliotheken Sie in Ihrem Projekt installieren möchten.

Unter # Pods for NotesApp schreiben Sie diese beiden Zeilen:

pod 'Realm', '~> 3.12.0'pod 'RealmSwift', '~> 3.12.0'

Ihr Podfile sollte so ähnlich aussehen, nachdem Sie diese Zeilen geschrieben haben:

platform :ios, '12.0'target 'NotesApp' do use_frameworks! # Pods for NotesApp pod 'Realm', '~> 3.12.0' pod 'RealmSwift', '~> 3.12.0' target 'NotesAppTests' do inherit! :search_paths end target 'NotesAppUITests' do inherit! :search_paths endend

Nun, da wir unsere Abhängigkeiten hinzugefügt haben, bitten wir CocoaPods, sie mit pod install

Dies wird einige Zeit dauern, wenn Sie CocoaPods zum ersten Mal verwenden. Keine Sorge, CocoaPods lädt nur ein paar erste Komponenten herunter. Dies wird nicht jedes Mal passieren, wenn du pod install.

Dein Terminal-Fenster wird so aussehen, sobald der Befehl ausgeführt wurde:

Terminal-Fenster

Wenn du das NotesApp.xcodeproj bereits geöffnet hast, schließe es danach. Wenn Sie CocoaPods verwenden, müssen Sie die Datei .xcworkspace anstelle der Standarddatei .xcodeproj verwenden. Öffnen Sie die NotesApp.xcworkspace Datei und gehen Sie zu Note.swift.

Das Model

Diese Klasse enthält unser Note Model Objekt, das ein paar grundlegende Eigenschaften enthält:

class Note { var identifier: String var content: String var lastEdited: Date init( identifier: String = UUID().uuidString, content: String, lastEdited: Date = Date()) { self.identifier = identifier self.content = content self.lastEdited = lastEdited }}

Standard Model Code, nichts besonderes passiert hier.

Wir haben auch eine Erweiterung zu unserem Notiz-Objekt in derselben Datei, die als Unterklasse des Protokolls Writeable

extension Note: Writable { func write(dataSource: DataSource) { self.lastEdited = Date() dataSource.store(object: self) } func delete(dataSource: DataSource) { dataSource.delete(object: self) }}

Innerhalb der Funktionen write und delete werden Sie feststellen, dass wir eine Eigenschaft DataSource haben. DataSource ist ein generisches Protokoll, das dabei helfen soll, die Änderung von Daten auf den höheren Ebenen unseres Codes so abstrakt wie möglich zu gestalten.

Hier ist die Protokolldefinition:

protocol DataSource { func store<T>(object: T) func delete<T>(object: T)}

Wenn Sie nicht mit Generika vertraut sind, hat jede unserer Funktionen einen T-Parameter, der im Wesentlichen bedeutet, dass es sich um jeden Objekttyp handeln kann. Dies wird in unserem Projekt nicht sehr stark genutzt, aber es könnte weiterentwickelt und genutzt werden, um mehrere DataSources mit verschiedenen Einschränkungen zu erstellen, welche Objekte sie speichern können.

Wir implementieren unser DataSource Protokoll in NoteDataSource. Auch hier gibt es nichts Besonderes, abgesehen von einem kleinen Leckerbissen, den ich der Erklärung halber erwähnen möchte.

Wenn wir store oder delete Objekte speichern, verwenden wir den folgenden Aufruf an NotificationCenter:

NotificationCenter.default.post(name: .noteDataChanged, object: nil)// We also have this extension of Notification.Name to make sending and receiving this notification simple.extension Notification.Name { static let noteDataChanged = Notification.Name(rawValue: "noteDataChanged")}

Im Wesentlichen informieren wir jedes Mal, wenn eine Notiz gespeichert oder gelöscht wird, alle Zuhörer darüber, dass sich unsere Daten geändert haben, damit sie ihre Benutzeroberfläche entsprechend aktualisieren können.

Nachdem wir alle Modelldateien und Klassen aus dem Weg geräumt haben, können wir mit der Implementierung von Realm beginnen!

Realm implementieren

Es gibt drei Schritte, um Realm in unser Projekt zu integrieren:

  1. Erstellen des Realm-Objekts
  2. Brücken zwischen unserem Realm-Objekt und unserem primitiven Notiz-Objekt
  3. Beginnen Sie mit dem Abrufen und Ändern von Daten mit Realm

Erstellen des Realm-Objekts

Dieser Schritt ist relativ einfach. Erstellen wir eine neue Swift-Datei namens RealmNote.swift. Innerhalb von RealmNote.swift importieren wir das RealmSwift-Framework und erstellen eine Klassendeklaration wie folgt:

import RealmSwiftclass RealmNote: Object {}

Wir werden die Klasse Object von Realm unterordnen, was uns die Verwendung von RealmNote in Realm-Datenbankfunktionen ermöglicht.

Nun fügen wir die drei Eigenschaften hinzu, die wir in unserem Notizmodell haben:

@objc dynamic var identifier: String = ""@objc dynamic var content: String = ""@objc dynamic var lastEdited: Date = Date()

Die @objc dynamic Teile unserer Variablendeklaration machen unsere Eigenschaften für Objective-C zugänglich, in dem viele der iOS-Schichten von Realm geschrieben sind. Außerdem kann Realm so auf Änderungen an unseren RealmNote Objekten warten.

Um unsere Klasse abzuschließen, überschreiben wir den class func primaryKey, der einen optionalen String (String?) mit dem Wert „identifier“ zurückgibt. Dies teilt Realm mit, dass der Primärschlüssel von RealmNote, eine Möglichkeit zur eindeutigen Identifizierung unserer Objekte, in der Eigenschaft „identifier“ gespeichert ist.

Nachdem Sie diese Schritte ausgeführt haben, wird Ihr RealmNote wie folgt aussehen:

class RealmNote: Object { @objc dynamic var identifier: String = "" @objc dynamic var content: String = "" @objc dynamic var lastEdited: Date = Date() override class func primaryKey() -> String? { return "identifier" }}

Das war’s für Schritt eins.

Überbrückung zwischen unserem Realm-Objekt und unserem primitiven Notiz-Objekt

Wir haben zwei separate Modellobjekte: Note und RealmNote. RealmNote wird intern verwendet, wenn wir mit Realm zu tun haben, um unsere Modellebene von unserer Benutzeroberfläche zu entkoppeln. Durch die Verwendung von zwei separaten Objekten können wir in Zukunft bei Bedarf auf Realm verzichten.

Erstelle in der RealmNote.swift-Datei eine Erweiterung von RealmNote:

extension RealmNote {}

Erstelle nun innerhalb der Erweiterung ein convenience init, das als einzige Eigenschaft ein Note aufnimmt. Dies wird uns erlauben, RealmNote Objekte zu erstellen, indem wir ein Note Objekt verwenden.

convenience init(note: Note) { self.init() self.identifier = note.identifier self.content = note.content self.lastEdited = note.lastEdited}

Großartig, jetzt, um RealmNote.swift abzuschließen, erstelle eine Note Variable innerhalb der Erweiterung, die von einem RealmNote initialisiert wird:

var note: Note { return Note(realmNote: self)}

Keine Sorge, wenn Xcode dir einen Fehler bezüglich des Initialisierers von Note gibt, wir werden das beheben.

Gehen Sie rüber zu Note.swift, wo wir die andere Hälfte unserer Bridge schreiben werden. Dieser Code ist im Wesentlichen dasselbe wie die Erweiterung von RealmNote.

extension Note { convenience init(realmNote: RealmNote) { self.init(identifier: realmNote.identifier, content: realmNote.content, lastEdited: realmNote.lastEdited) } var realmNote: RealmNote { return RealmNote(note: self) }}

Gut, das ist Schritt zwei. Wir können jetzt von einem Note auf ein RealmNote und von einem RealmNote auf ein Note zugreifen. Das bedeutet auch, dass dieser Code vollkommen gültig ist:

Note(content: "Example").realmNote.note.realmNote.note.realmNote.note.realmNote// and so on...

Späße beiseite, lasst uns unsere Anwendung mit Schritt drei abschließen.

Beginnen Sie mit dem Abrufen und Ändern von Daten mit Realm

Kopf in NoteDataSource.swift, und import RealmSwift vor der Klassendeklaration. Bevor wir Realm-Objekte ändern, löschen und abrufen können, benötigen wir eine Instanz der Realm-Datenbank. Ersetzen Sie NoteDataSource’s init mit diesem:

var realm: Realminit() { // Load our data self.realm = try! Realm()}

Damit wird eine Instanz der Realm-Datenbank erstellt. In der Produktion möchten Sie wahrscheinlich nicht den Operator bang (!) verwenden, wenn Sie die Instanz erstellen, da Ihre Anwendung abstürzt, wenn die Datenbank nicht verfügbar ist.

Als nächstes bearbeiten wir die Funktion store, um Objekte in unserer Datenbank zu speichern.

Das Schreiben mit Realm ist einfach:

try? self.realm.write {}

Innerhalb dieses Codeblocks können wir Objekte in der Datenbank aktualisieren. Schreiben Sie Folgendes:

self.realm.add(note.realmNote, update: true)

Damit wird entweder ein neues RealmNote in der Datenbank erstellt oder ein bestehendes aktualisiert, falls eines vorhanden ist. Das war’s! Wir speichern jetzt Objekte in der Realm-Datenbank (der Aufruf der Schreibfunktion für Notizen erfolgt in NoteDetailController.swift, falls Sie die Funktion sehen möchten, die tatsächlich für diesen Schreibvorgang verwendet wird)

Schreiben wir nun unsere delete-Funktion. Aufgrund der Art und Weise, wie wir unsere Bridge geschrieben haben (ohne Realm zu konsultieren, wenn wir ein RealmNote aus einem Note erstellen), müssen wir das Objekt direkt aus der Datenbank abrufen, indem wir den Bezeichner der Notiz verwenden, anstatt die realmNote-Eigenschaft zu benutzen.

Das ist ganz einfach:

if let realmNote = self.realm.object(ofType: RealmNote.self, forPrimaryKey: note.identifier) {}

Damit wird Realm aufgefordert, ein RealmNote-Objekt mit dem Bezeichner oder Primärschlüssel note.identifier aus der Datenbank abzurufen.

Das kann ein wenig problematisch sein. Aus irgendeinem Grund stürzt die Anwendung ab, wenn wir die herkömmliche write-Funktion für Realm verwenden. Als Abhilfe ist dieser Code vollkommen gültig und führt im Wesentlichen die gleiche Aufgabe aus wie write:

self.realm.beginWrite()self.realm.delete(realmNote)try? self.realm.commitWrite()

Wir beginnen mit dem Schreiben, löschen das Objekt und bestätigen das Schreiben.

Damit haben wir eine funktionierende Notizanwendung erstellt!

Fazit

Ich hoffe, dass Ihnen dieses Tutorial zur Verwendung der Realm-Datenbank gefallen hat. Es hat mir sehr viel Spaß gemacht und ich kann es kaum erwarten, diese Serie weiterzuentwickeln und unserer App im Laufe der Zeit weitere Funktionen wie Siri Shortcuts, CloudKit und mehr hinzuzufügen. Danke fürs Lesen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.