In diesem Teil behandeln wir:
Was ist Realm
RealmSwift
Erstellen eines komplexen Realm-Modells
Warum wir @objc und dynamic in Property verwenden
Zu-Eins- und Zu-Viele-Beziehung im Realm
Wie man benutzerdefinierte Enumerationen im Realm speichert
Was ist RealmOptional und wie man eine optionale atomare Eigenschaft speichert
Wie funktioniert eine berechnete Eigenschaft als transiente Eigenschaft im Realm
Indizierung zur Leistungssteigerung
Was ist das Verknüpfen von Objekten im Realm
Komplexe Prädikatabfragen
CRUD-Operation
Was sind Live-Ergebnisse im Realm
Dinge vermieden, wenn Realm-Objekte ändern
Realm ist eine plattformübergreifende mobile Objektdatenbank. Es ist sehr schnell, performant und einfach zu bedienen im Vergleich zu Core Data und Sqlite. Es verwendet seinen Speichermechanismus, um Objekte als JSON auf der Festplatte zu speichern, im Vergleich zu Core Data, das Sqlite als Backend verwendet. Es ist in plattformübergreifendem C ++ geschrieben und funktioniert daher auf Android, iOS, macOS oder jeder anderen Plattform genauso.
RealmSwift
Der größte Teil von Realm ist Open Source, aber die geheime Sauce hinter der Realm-Plattform ist die Kern-DB-Engine, die in C ++ von Grund auf neu geschrieben wurde. RealmSwift ist ein Wrapper um das Objective-C Realm Framework und Objective-C Realm Framework ist ein Wrapper um Realm Core DB Engine.
Erste Schritte
In diesem Tutorial werden wir an diesen Modellen arbeiten, wie in Abbildung 1 gezeigt
Benutzer → Es ist ein Modell, das Benutzerinformationen enthält, in denen userId
es ist primär. Es hat auch eine Eins-zu-Eins-Beziehung zum Passport-Modell und zu viele Beziehungen zu Todo-Aufgaben. (Benutzer kann nur einen Pass haben und viele Aufgaben haben)
Passport → Es ist ein Modell, das Passinformationen eines Benutzers enthält und auch einen Reverse-Back-Link von User
Objekt.
Todo → Es ist ein Modell enthält Aufgaben eines Benutzers und hat auch einen Reverse-Back-Link von User
Objekt.
Abbildung 1 Benutzermodell
Wie in Abbildung 2 gezeigt, haben wir ein Benutzermodell erstellt und einige Eigenschaften hinzugefügt:
Zuerst erben wir User
Klasse von Object
wodurch es Realm Object
. Realm-Objekte sind im Grunde ein Standarddatenmodell, ähnlich wie jedes andere Standarddatenmodell, das Sie in Ihren Apps definiert haben. Der einzige Unterschied besteht darin, dass sie durch ihre Ausdauer und Fähigkeiten unterstützt werden. Wenn Sie sich alle Object
ansehen, können Sie auf Ihr Schema schließen. Jedes Modell, das Sie beibehalten möchten, müssen Sie von der Objektklasse erben.
firstName
speichert den Vornamen des Benutzers als String
. Da RealmSwift
ein Wrapper um das Objective-C-Realm-Framework ist, sind Typen wie String, Date und Data Unterklassen von NSObject in Objective-C, sodass Sie sie auch in Swift als Objekttypen betrachten können. Darüber hinaus bedeutet @objc, dass Sie Ihren Swift-Code (Klasse, Methode, Eigenschaft usw.), um von Objective-C aus sichtbar zu sein, während dynamic bedeutet, dass Sie Objective-C dynamic dispatch verwenden möchten. Um einfache Swift-Objektspeicher im Datenbankbereich zu erstellen, wird die dynamische Dispatch-Funktion von Objective-C verwendet, um unter der Haube zu arbeiten
userId
speichert die Benutzer-ID, die als Primärschlüssel fungiert. Sie können eine der Eigenschaften Ihres Objekts als Primärschlüssel festlegen. Normalerweise Eigenschaft, die sich eindeutig identifiziert, das ist ein Hauptkandidat für einen Primärschlüssel. Es hilft Ihnen, eine schnelle Suche oder Bearbeiten von Objekten in einer Datenbank. Wie in Abbildung 2 gezeigt, machen wir userId
Primärschlüssel durch Überschreiben primarykey
statische Funktion. Die Standardimplementierung dieser Methode gibt null zurück. Hinweis userId
fungiert als Objective C primitive Int Typ, da es ein Wrapper um Objective C Realm ist
passport
Eigenschaft speichert die Benutzerpassinformationen, die ein anderes Realm-Objekt sind. Wir haben eine Eins-zu-Eins-Beziehung zum Passport-Modell aufgebaut. Eins-zu-Eins-Beziehung / Objekt-Verknüpfung, bei der ein Realm-Objekt auf ein anderes Realm-Objekt zeigt. Wenn Sie eine Beziehung zu einem anderen Realm-Objekt erstellen, muss dessen Eigenschaft einen optionalen Typ haben. In der Variablenzeigerreferenz von Passport
Objekt speichert
privateUserType
ist die Wrapper-Eigenschaft von UserType
Da UserType swift enum ist, können wir nicht direkt auf Realm speichern. Alle Fallwerte hätten einen implizit zugewiesenen Rohwert, der dem Namen des Falls entspricht. Sie verwenden diesen Rohwert, um die Enum-Optionen als Int
in Realm beizubehalten. Der Client greift jedoch auf die berechnete Enum-Eigenschaft zu und unter der Haube wird der Rohwert / Atomwert der Enum in der Datenbank gespeichert, die für den Client nicht sichtbar ist.
Die Eigenschaften String, NSDate und NSData können mit der Standard-Swift-Syntax als optional oder nicht optional deklariert werden.Optionale numerische Typen werden mit RealmOptional deklariert. Da RealmSwift ein Wrapper um Objective C Realm ist und es in Objective C kein optionales Int gibt, hat Realm für dieses Szenario den Typ RealmOptional erstellt. Alle Objective C primitiven Typ erfordern in Swift mit Optional müssen Sie RealmOptional verwenden. Hinweis: RealmOptional-Eigenschaften können nicht als dynamic und @objc Schlüsselwort deklariert werden, da generische Eigenschaften nicht in der Objective C-Laufzeit dargestellt werden können, die für den dynamischen Versand dynamischer Eigenschaften verwendet wird und immer mit let deklariert werden sollte. Da es sich um eine Realm-Klasse handelt, verfügt sie über alle Funktionen, die Realm und Objekt haben. Wie in Abbildung 2 gezeigt isEmailSubscriptionEnable
wir deklarieren als RealmOptional
Bool bedeutet, dass es null sein kann, das wir mit let verwendet haben, da es ein Referenztyp ist und wir nicht möchten, dass sich seine Adresse in Zukunft ändert.
Wie in Abbildung 2 gezeigt, kann der Benutzer viele Todos haben, die eine Sammlung von Realm-Todo-Objekten sind. Liste als Realm-Klasse Sammlung der Realm-Objektinstanzen zu halten. Wir haben eine To-Many-Beziehung mit dem Todo-Modell erstellt. Zu-Viele-Beziehung, in der ein Realm-Objekt auf die Sammlung des Realm-Objekts zeigt. Wenn Sie ein normales Swift-Array zum Speichern einer Realm-Objektsammlung verwenden, erhalten Sie eine Ausnahme. Hinweis: Wie RealmOptional kann List nicht als dynamic und @objc Schlüsselwort deklariert werden, da es sich um eine Realm-Klasse mit allen integrierten Funktionen handelt. List ist Array für integrierte Methoden und den Zugriff auf Objekte mithilfe indizierter Subskription sehr ähnlich. Liste, wie Sie sehen, ist typisiert und alle Objekte sollten vom gleichen Typ sein
isUserHasTodos
ist eine berechnete Swift-Eigenschaft und wird nicht in der Realm-Datenbank gespeichert, die zurückgegeben wird, wenn der Benutzer einige Aufgaben zu erledigen hat oder nicht.
Schließlich machen wir userId
und firstName
als indizierte Eigenschaften. Durch Überschreiben der indexedProperties
statischen Methode stellen wir ein Array von Eigenschaften in Zeichenfolgenform bereit. Wir indizieren auf Eigenschaften, um die Zugriffszeiten beim Filtern oder Abfragen der Datenbank zu verbessern
Abbildung 2 Passmodell
Wie in Abbildung 3 gezeigt, haben wir ein Passmodell mit den wenigen Eigenschaften erstellt
passportNumber
speichert die Passinformationen und expiryDate
speichert das Ablaufdatum des Passes, den wir diese Eigenschaften zu speichern, deshalb haben wir verwenden Sie @objc
mit dynamic
Schlüsselwort realm zu sagen, tun Sie Ihre unter der Haube Magie
Wir haben passport
Eigenschaft auf User
Modell, das bedeutet User
Objekt haben ihre passport
Objektreferenz Was ist, wenn wir wollen passport Objekt auch wissen, welcher Benutzer diesen Pass hat / einen Verweis auf den Benutzer hat, der diesem Pass zugeordnet ist. Wir haben die Backlinks mit LinkingObjects erstellt, was bedeutet, dass wir die ofUser
-Eigenschaft in Passport erstellt haben, die eine Referenz aller Benutzerobjekte enthält, die das Passport-Objekt in seiner passport
-Eigenschaft zuweisen. In Core Data wird es als inverse Beziehung bezeichnet. Es ist eine dynamische Sammlung, die Ihnen mitteilt, wer mit dem aktuellen Objekt verknüpft ist.
Figure 3
As shown in Figure 4 we created Todo
Realm model with has a backlink to the all the users pointing to particular task .
Abbildung 4 Wir haben die Modell- / Schemaerstellung abgeschlossen und jetzt ist es an der Zeit, eine tatsächliche CRUD-Operation durchzuführen
Objekt zum Realm hinzufügen
Wir klären zuerst ein Konzept, dann können wir problemlos Objekte im Realm hinzufügen
Wie in Abbildung 5 gezeigt, erhalten wir zunächst eine Instanz des Standardwerts Realm
, indem wir sie ohne Argumente initialisieren. Die einzige Möglichkeit, über die Realm-Instanz auf die Datenbank zuzugreifen. Eine Realm
-Instanz (auch als „Realm“ bezeichnet) stellt eine Realm-Datenbank dar.Realms können entweder auf der Festplatte (siehe init(path:)
) oder im Speicher (siehe Configuration
) gespeichert werden. Realm
Instanzen sind nicht threadsicher und können nicht über Threads oder Dispatch-Warteschlangen hinweg gemeinsam genutzt werden. Sie müssen für jeden Thread, in dem auf einen Realm zugegriffen wird, eine neue Instanz erstellen.
Wie in Abbildung 5 gezeigt, da es sich um eine neue App handelt und kein Objekt in der Datenbank gespeichert wurde realm.isEmpty
gibt true bedeutet, dass die Datenbank leer ist, wie auf der Konsole gedruckt
Abbildung 5
Wie in Abbildung 6 gezeigt, haben wir eine Reihe von Aufgaben ausgeführt
Wir erhalten die Instanz von Realm
Datenbank
Passport
und drei Aufgaben als todos
Erstellt User
Objekt und weisen Passport und todos zu. Zusätzlich zu dieser initialisierten optionalen Realm-Eigenschaft, die isEmailSubscriptionEnable
und Usertype
enum mit Gold-Mitgliedschaft
ist, wie in Abbildung 6 gezeigt, ist die Realm-Datenbank immer noch leer und das inverse Beziehungs- / Verknüpfungsobjekt funktioniert auch nicht, da wir diese Objekte nicht zum Realm hinzugefügt haben. Realm-Objekte (User, Passport, Todo) können wie normale Swift-Objekte instanziiert und als nicht verwaltete Objekte (dh noch nicht zu einem Realm hinzugefügt) verwendet werden. Um diese Objekte von Realm verwalten zu lassen, müssen Sie sie in Realm hinzufügen
Abbildung 6 Wie in Abbildung 7 gezeigt, fügen wir schließlich das Objekt in die Realm-Datenbank ein. Wir haben Cascading Insert in die DB durchgeführt.
Hinweis: Alle Änderungen an einem Objekt (Hinzufügen, Ändern und Löschen) müssen innerhalb einer Schreibtransaktion erfolgen.Realm-Schreiboperationen sind synchron und blockierend, nicht asynchron. Wenn Thread A eine Schreiboperation startet und Thread B eine Schreiboperation auf demselben Realm startet, bevor Thread A beendet ist, muss Thread A seine Transaktion beenden und festschreiben, bevor die Schreiboperation von Thread B stattfindet. Schreibvorgänge werden immer automatisch aktualisiert, sodass keine Race Condition erstellt wird. Schreiboperation kann Fehler auslösen, wie der Speicherplatz knapp wird
Wir haben Ihrem Realm einen Benutzer hinzugefügt, und da er auf Passport und todos verweist, werden diese Objekte auch zum Realm hinzugefügt.
Durch Hinzufügen eines nicht verwalteten Objekts zu realm haben wir diese Objekte jetzt verwaltet, wie in der Konsole gezeigt. Jetzt können Sie auch auf das Benutzerobjekt zugreifen. Jetzt ist unsere Datenbank nicht mehr leer
Wir fügen endlich ein Objekt in die Datenbank ein, da wir ein Objekt einfügen, das wir im Schreibtransaktionsblock hinzufügen müssen, und wir fügen es dem Realm hinzu, indem wir die Add-Methode für die Realm-Instanz verwenden. Wenn nun versucht wird, ein anderes separates Objekt mit demselben Primärschlüssel des Benutzers mit userId = 1
als separates Objekt zum Realm hinzuzufügen, wird eine Ausnahme ausgelöst
Abbildung 7 Überprüfen Sie den physischen Speicher des Objekts
Wenn Sie diesen Befehl am Debugger-Ausgang ausführen, erhalten Sie die Adresse der Datei, in der Ihre Daten gespeichert sind
Abbildung 8
Öffnen in Realm Studio Realm Studio ist unsere Premiere Entwickler-Tool, gebaut, so dass Sie ganz einfach die Realm-Datenbank und Realm-Plattform verwalten können. Mit Realm Studio können Sie lokale und synchronisierte Realms öffnen und bearbeiten sowie jede Realm-Objektserverinstanz verwalten. Laden Sie es jetzt für Mac, Windows oder Linux herunter.
Abbildung 9
Wie in Abbildung 10 Daten tatsächlich gespeichert. Sie fragen sich vielleicht Article
und Person
Klasse auch dort, weil in einigen meiner Projektklasse Modelle Person und Artikel erstellen. Wenn die Anwendung ausgeführt wird, überprüft Realm alle Klassen in Ihrer App und Ihren Frameworks und findet die Klassen, die die Objektklasse von Realm unterklassen. Die Liste dieser Klassen wird als Ihr Datenschema betrachtet, das auf der Festplatte oder im Arbeitsspeicher beibehalten wird.
Abbildung 10 Objekt aus Realm abrufen
Der Prozess des Abrufs aller Benutzerdatensätze aus Realm hat folgende Aufgaben
Wir erhalten die Instanz der Realm-Datenbank und sie kann Folgendes auslösen: Ein NSError
wenn der Realm nicht initialisiert werden konnte. Standard-Realm wird erstellt, wenn wir init()
ohne Parameter aufrufen
Aufgerufene objects-Methode in der Realm-Datenbank, die alle Objekte des angegebenen Typs zurückgibt, die im Realm gespeichert sind, und ein Ergebnis mit allen Objekten zurückgibt, wie in Abbildung 11 gezeigt
Gedrucktes Objekt auf der Konsole, um Daten zu validieren, ist da und die Verknüpfung von Objekten funktioniert einwandfrei
Abbildung 11
datensatz von seinem Primärschlüssel, der auch eine indizierte Eigenschaft ist, sodass wir das optionale Benutzerobjekt erhalten, da ein Objekt mit diesem Primärschlüssel möglicherweise nicht vorhanden ist. Der Primärschlüssel kann Int
oder String
sein. Die Empfehlung ist, String.
zu verwenden, um bestimmte Objekte in einer Realm-Datenbank eindeutig zu identifizieren.Sobald ein Primärschlüsselwert für ein bestimmtes Objekt festgelegt wurde, kann er niemals geändert werden.
Abbildung 12 Wie gezeigt, haben wir mit einem Prädikat gefiltert Hier ist die Liste der Operatoren, die wir verwendet haben
filter → entspricht Werten gleich
filter case insensitive → entspricht Werten gleich ignore case
IN {1,2,3} filter → entspricht Wert aus einer Liste von Werten.
filter → trifft zu, wenn der Vorname-Wert mit a beginnt.
filter → Übereinstimmungen, wenn der FirstName-Wert mit li übereinstimmt.
Prädikat mit Passport-Objekt Wir möchten Benutzer filtern, die Passnummer haben == ‚pass1‘
Prädikat mit Todos-Objekt Wir möchten Benutzer filtern, die eine tdodo enthält Details == ‚Need ot create RxSwift blog‘
Für erweiterte Abfragen wird dringend empfohlen, https://academy.realm.io/posts/nspredicate-cheatsheet/ dies NSPredicate cheatsheet
Hinweis: Was Sie als „transiente (berechnete) Eigenschaften“ bezeichnen, bezeichnet Realm als „ignorierte Eigenschaften“. Dies sind Eigenschaften, die von Realm größtenteils ignoriert werden, sodass sie nicht in der DB-Datei gespeichert werden, außerhalb von Schreibtransaktionen mutiert werden können usw.Dies bedeutet jedoch auch, dass sie nicht von vielen Funktionen nicht ignorierter Eigenschaften wie Abfragen profitieren. (querying for Realm objects can only be done with non-computed, Realm-persisted properties)
Figure 13
As shown in Figure 14 we sorted results with the firstName
property on User model
Figure 14
Live-Ergebnisse
Letztes Thema zum Abrufen aus dem Realm-Bereich
Realm-Ergebnismengen geben immer die neuesten Daten zurück. Daten in Ergebnissen sind nie veraltet. Dies bedeutet, dass Sie die Ergebnisse niemals von der Festplatte neu laden oder die In-Memory-Daten manuell aktualisieren müssen.
Wie in Abbildung 15 gezeigt, haben wir den neuen Benutzer erhalten und nicht mit der realm.objects
-Methode abgerufen. Wenn Sie aus dem Core Data-Hintergrund kommen, müssen Sie das Objekt erneut vom Stapel holen
Das Lesen und Schreiben kann an verschiedenen Stellen im Projekt, in verschiedenen Threads, von verschiedenen Prozessen oder bei Verwendung der Realm-Plattform von überall auf der Welt erfolgen. Jede Klasse in der App kann sich auf die Geschäftslogik konzentrieren und den Begriff veralteter oder zwischengespeicherter Daten vergessen, da Realm-Objekte immer auf dem neuesten Stand sind.
Abbildung 15
Objekt auf Realm ändern
Wie in Abbildung 16 gezeigt, ändern wir den Primärschlüssel und erhalten „Primärschlüssel kann nicht geändert werden, nachdem ein Objekt eingefügt wurde.“ ausnahme, da wir den Primärschlüssel nicht aktualisieren können. Von Realm Wenn der Primärschlüssel zu einem Realm hinzugefügt wird, kann der Primärschlüssel nicht geändert werden. Problemumgehung → Entfernen Sie das Objekt und fügen Sie es erneut ein oder sehen Sie sich diese Frage im Stackoverflow an
16
Wie in Abbildung 17 gezeigt, können Sie kein Objekt ändern, das aus einem Bereich außerhalb des Schreibtransaktionsblocks abgerufen wurde Wenn Sie versuchen, außerhalb dieses Bereichs zu ändern, erhalten Sie die Ausnahme „‚Beim Versuch, ein Objekt außerhalb einer Schreibtransaktion zu ändern, rufen Sie zuerst beginWriteTransaction in einer RLMRealm—Instanz auf.“
Figure 17
As shown in Figure 18 as we modify object in write
transaction block it will persist that object into the disk as well as shown in Figure 19 default.realm
file now has a updated firstName
value of User
Abbildung 18
Abbildung 19
Letztes Beispiel ist sehr interessant Wir haben folgende Aufgaben ausgeführt, um den Benutzer mit dem neuen Benutzer zu aktualisieren
Wir erhalten den Benutzer mit seinem Primärschlüssel userId
welches ist 1
Erstellt neu User
mit dem gleichen Primärschlüssel
Bei einer Schreibtransaktion nennen wir add batch update-Methode Mit update = true wird der Benutzer mit Primärschlüssel = 1 aktualisiert. If update = false it will throw an exception since two objects can’t have same primary key as shown in Figure 20 and 21
Figure 20
Figure 21
Delete Object From Realm
Any objects currently wenn Sie mit den gelöschten verknüpfen, wird ihre Verknüpfungseigenschaft auf Null gesetzt. Wenn diese Objekte aus Listeneigenschaften verknüpft sind, werden sie aus den betreffenden Listen entfernt.
As shown in Figure 22 and 23 we deleted User object having firstName == ‚ali new User‘
Figure 22
Figure 23
As shown in Figure 24 we empty Realm database using deleteAll()
method in realm-Objekt. Wie in Abbildung gezeigt realm.isEmpty
gibt true zurück
Abbildung 24
Manchmal müssen Sie eine Art Hierarchie zwischen Realm-Objekten erstellen, genau wie Sie es mit Swift-Klassen gewohnt sind. Leider unterstützt Realm derzeit keine Objektvererbung. Problemumgehung: https://forum.realm.io/t/inheritance-with-realm-confusion/153
Useful Links
https://www.raywenderlich.com/9220-realm-tutorial-getting-started https://www.appcoda.com/realm-database-swift/
https://realm.io/docs/swift/latest/#to-many-relationships https://realm.io/docs/swift/latest/#optional-properties
https://academy.realm.io/posts/nspredicate-cheatsheet/
https://academy.realm.io/posts/nspredicate-cheatsheet/