w tej części omówimy:
co to jest Realmswift
Tworzenie złożonego modelu Realm
dlaczego używamy @objc i dynamic w właściwościach
To-One i to-Many Relationship w Realm
Jak przechowywać niestandardowe enum w Realm
co to jest RealmOptional i jak przechowywać Swift opcjonalna własność atomowa
Jak Computed Property działa jako Transient Property w realm
jak zrobić indeksowanie dla zwiększenia wydajności
co to jest łączenie obiektu w Realm
złożone zapytania Predykatowe
operacja CRUD
co to są wyniki na żywo w Realm
rzeczy unikane, gdy Modyfikuj Obiekty Realm
Realm jest wieloplatformową mobilną bazą danych obiektów. Jest bardzo szybki, wydajny i łatwy w użyciu w porównaniu do danych podstawowych i Sqlite. Wykorzystuje swój mechanizm przechowywania do przechowywania obiektu jako JSON na dysku w porównaniu do podstawowych danych, które używają SQLite jako swojego zaplecza. Jest napisany w wieloplatformowym C++ , więc działa dokładnie tak samo na Androidzie, iOS, macOS lub dowolnej innej platformie.
RealmSwift
Większość Realm jest open-source, ale sekretem stojącym za platformą Realm jest Core dB engine napisany od podstaw w C++. RealmSwift jest owijką wokół Objective-C Realm framework i Objective-C Realm framework jest owijką wokół rdzenia silnika dB Realm.
wprowadzenie
w tym samouczku będziemy pracować nad tymi modelami, jak pokazano na rysunku 1
User → jest to model zawierający informacje o użytkowniku, w którymuserId
jest to podstawowy. Ma również związek To-one z modelem paszportu i to-wiele relacji z zadaniami Todo. (Użytkownik może mieć tylko paszport i mieć wiele zadań todo)
Passport → jest to model zawierający informacje paszportowe użytkownika, a także posiada link zwrotny User
obiektu.
Todo → jest to model zawierający zadania użytkownika, a także posiada link zwrotny User
obiektu.
Rysunek 1ak pokazano na rysunku 2, stworzyliśmy model użytkownika i dodaliśmy kilka właściwości:
najpierw dziedziczymy User
klasa z Object
co sprawia, że jest to User
Realm Object
. Obiekty Realm są w zasadzie standardowym modelem danych, podobnie jak każdy inny standardowy model danych zdefiniowany w aplikacjach. Jedyną różnicą jest to, że są wspierani przez trwałość i zdolności Królestwa. Patrząc na wszystkieObject
klasy Realm są w stanie wywnioskować twój schemat. Każdy model, który chcesz utrzymywać, musisz dziedziczyć z klasy Object.
firstName
przechowuje imię użytkownika jakoString
. Ponieważ RealmSwift
jest opakowaniem wokół typów frameworka Objective-C, takich jak String, Date i Data, są podklasami NSObject w Objective-C, więc można je również rozważyć w Swift. Oprócz tego @objc oznacza, że chcesz swój kod Swift (Klasa, metoda, właściwość itp.) być widocznym z Objective-C, podczas gdy dynamic oznacza, że chcesz użyć Objective-C Dynamic dispatch. Aby zrobić proste szybkie przechowywanie obiektów w serwerze database Realm używa funkcji dynamicznej wysyłki Objective-C do pracy pod maską
userId
Przechowuje identyfikator użytkownika, który działa jako klucz podstawowy. Jako klucz podstawowy można ustawić jedną z właściwości obiektu. Zazwyczaj właściwość, która jednoznacznie identyfikuje się, czyli jest głównym kandydatem na klucz podstawowy. Pomaga w szybkim wyszukiwaniu lub edycji obiektu w bazie danych. Jak pokazano na rysunku 2 wykonujemyuserId
klucz podstawowy poprzez nadpisanieprimarykey
funkcji statycznej. Domyślna implementacja tej metody zwraca nil. UwagauserId
działa jako obiekt typu Objective C primitive int, ponieważ jest opakowaniem wokół Objective C Realm
passport
właściwość przechowuje informacje o paszporcie użytkownika, które są innym obiektem Realm. Stworzyliśmy relację to-One z Modelem paszportowym. To-jeden związek / obiekt , w którym jeden obiekt realm wskazuje na inny obiekt realm. Gdy tworzysz relację z innym obiektem Realm, jego właściwość musi być typu opcjonalnego. W passport variable pointer reference of Passport
object will store
privateUserType
is the wrapper property of UserType
since UserType is swift enum We can ’ t store directly on Realm. Wszystkie wartości case będą miały domyślnie przypisaną wartość surową pasującą do nazwy przypadku. Użyjesz tej wartości surowej, aby zachować opcje enum jako Int
w Realm. Ale Klient uzyskuje dostęp do właściwości computed enum i pod maską enum raw value / Atomic value przechowuje w bazie danych, która nie jest widoczna dla klienta.
właściwości String, nsdate i nsdata mogą być zadeklarowane jako opcjonalne lub nieobowiązkowe przy użyciu standardowej składni Swift.Opcjonalne typy liczbowe są deklarowane za pomocą RealmOptional. Ponieważ RealmSwift jest owijką wokół Objective C Realm i nie ma opcjonalnego Int w Objective C, dlatego Realm stworzył Typ RealmOptional dla tych scenariuszy. Wszystkie obiektywy typu C wymagają W Swift z opcjonalnym trzeba użyć RealmOptional . Notatka: właściwości RealmOptional nie mogą być deklarowane jako słowa kluczowe dynamic i @objc, ponieważ właściwości ogólne nie mogą być reprezentowane w Objective C runtime, który jest używany do dynamicznego wysyłania właściwości dynamicznych i powinien być zawsze deklarowany za pomocą let. Ponieważ jest klasą Realm, posiada wszystkie funkcje, które posiada obiekt Realm persist. Jak pokazano na rysunku 2 isEmailSubscriptionEnable
deklarujemy jako RealmOptional
Bool oznacza, że może być nil, którego użyliśmy z let, ponieważ jest to typ referencyjny i nie chcemy, aby jego adres zmieniał się w przyszłości.
Jak pokazano na rysunku 2 Użytkownik może mieć wiele todos, które jest zbiorem obiektów Realm Todo . Lista jako klasa Realm do przechowywania kolekcji instancji obiektu Realm. Stworzyliśmy relację to-Many z Modelem Todo. To-wiele relacji, w której jeden obiekt realm wskazuje na zbiór obiektu realm. Jeśli użyjesz zwykłej tablicy Swift do przechowywania kolekcji obiektów Realm, otrzymasz wyjątek. Uwaga: podobnie jak lista RealmOptional nie może być zadeklarowana jako słowo kluczowe dynamic i @ objc, ponieważ jest to klasa Realm ze wszystkimi wbudowanymi funkcjami. Lista jest bardzo podobna do tablicy dla wbudowanych metod i dostępu do obiektów za pomocą indeksowanego subskryptora. Lista jak widzisz jest wpisana i wszystkie obiekty powinny być tego samego typu
isUserHasTodos
jest obliczoną właściwością swift i nie będzie przechowywana w bazie danych realm, która zwraca, jeśli użytkownik ma jakieś zadania do wykonania lub nie.
w końcu tworzymyuserId
IfirstName
jako właściwości indeksowane. Poprzez nadpisanie metody statycznejindexedProperties
udostępniamy tablicę właściwości w postaci String. Indeksujemy właściwości, aby poprawić czas dostępu podczas filtrowania lub odpytywania bazy danych
rysunek 2 model paszportu
jak pokazano na rysunku 3, stworzyliśmy model paszportu z kilkoma właściwościami
passportNumber
przechowuje informacje o paszporcie iexpiryDate
przechowuje datę ważności paszportu chcemy, aby te właściwości przechowywały dlatego my użyj @objc
za pomocą dynamic
słowa kluczowego, aby powiedzieć realm zrobić swoją magię pod maską
stworzyliśmy passport
właściwość na User
model, co oznacza User
object have their passport
Object reference co zrobić, jeśli chcemy obiekt passport również wiedzieć, który Użytkownik ma ten paszport / mieć odniesienie do użytkownika powiązanego z tym paszportem. Backlinki stworzyliśmy za pomocą LinkingObjects, co oznacza, że stworzyliśmy ofUser
właściwość w Passport, która zawiera odniesienia do wszystkich obiektów Użytkownika, które przypisują obiekt Passport w swojej właściwości passport
. W podstawowych danych nazywa to odwrotną relacją. Jest to dynamiczna kolekcja informująca, kto łączy się z bieżącym obiektem.
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 .
Rysunek 4
zakończyliśmy tworzenie modelu / schematu i teraz nadszedł czas na rzeczywistą operację CRUD
Dodaj obiekt do Realm
najpierw wyczyścimy jakąś koncepcję, a następnie będziemy mogli łatwo dodać obiekt do Realm
jak pokazano na rysunku 5 zaczynamy od uzyskania instancji domyślnego Realm
inicjalizując go bez żadnych argumentów. Jedyny sposób na dostęp do bazy danych poprzez instancję realm. InstancjaRealm
(zwana także „Realm”) reprezentuje bazę danych Realm.Domeny mogą być przechowywane na dysku (patrz init(path:)
) lub w pamięci (patrz Configuration
) zobaczymy w kolejnych częściach. Realm
nie są bezpieczne dla wątków i nie mogą być współdzielone między wątkami ani kolejkami wysyłania. Musisz utworzyć nową instancję dla każdego wątku, w którym dostęp do serwera będzie możliwy.
jak pokazano na rysunku 5, ponieważ jest to świeża aplikacja i żaden obiekt nie został zapisany w bazie danych realm.isEmpty
zwraca true, co oznacza, że baza danych jest pusta, jak wydrukowano na konsoli
rysunek 5
jak pokazano na rysunku 6 wykonaliśmy liczbę zadań
otrzymujemy instancję Realm
baza danych
utworzonaPassport
i trzy zadania jako todos
utworzył User
obiekt i przypisał do niego passport i todos. Oprócz tej zainicjalizowanej opcjonalnej właściwości Realm, która jest isEmailSubscriptionEnable
I Usertype
enum with gold membership
Jak pokazano na rysunku 6 baza danych realm nadal pusta i odwrotna relacja/ łączenie obiektu też nie działa, ponieważ nie dodaliśmy tych obiektów do realm. Obiekty Realm (User, Passport, Todo)mogą być tworzone i używane jako obiekty niezarządzane (tj. nie są jeszcze dodawane do Realm), podobnie jak zwykłe obiekty Swift. Aby te obiekty były zarządzane przez Realm, musisz dodać je do Realm
rysunek 6
jak pokazano na rysunku 7 W końcu wstawiamy obiekt do bazy danych Realm. Wykonaliśmy kaskadowy wkład do DB.
Uwaga: wszystkie zmiany w obiekcie (dodanie, modyfikacja i usunięcie) muszą być wykonane w ramach transakcji zapisu.Operacje zapisu w serwerze Realm są synchroniczne i blokowane, a nie asynchroniczne. Jeśli wątek a rozpoczyna operację zapisu, to wątek B rozpoczyna operację zapisu na tym samym serwerze przed zakończeniem wątku a, wątek a musi zakończyć i zatwierdzić swoją transakcję przed zakończeniem operacji zapisu w wątku B. Operacje zapisu zawsze odświeżają się automatycznie, więc nie są tworzone żadne warunki wyścigu. Operacja zapisu może spowodować błąd, taki jak brak miejsca na dysku
dodaliśmy użytkownika do Twojego Realm, a ponieważ odwołuje się do passport i todos, obiekty te są również dodawane do Realm.
dodając niezarządzany obiekt do realm sprawiliśmy, że te obiekty zostały teraz zarządzane tak, jak pokazano w konsoli nasze linki zwrotne działają. Teraz passport może również uzyskać dostęp do obiektu użytkownika. Teraz nasza baza danych nie jest już pusta
w końcu wstawiamy obiekt do bazy danych ponieważ wstawiamy obiekt musimy dodać do bloku transakcyjnego write i dodajemy do realm używając metody add na instancji Realm. Teraz, jeśli inny osobny obiekt z tym samym kluczem podstawowym Użytkownika o userId = 1
zostanie dodany jako oddzielny obiekt do serwera, zostanie wywołany wyjątek
rysunek 7 sprawdź obiekt fizycznie przechowuj
uruchamiając to polecenie na wyjściu debuggera, otrzymasz adres Pliku Realm, w którym przechowywane są Twoje dane
Rysunek 8
otwórz default.realm
w Realm Studio Realm Studio to nasze premierowe narzędzie programistyczne, zbudowane tak, abyś mógł łatwo zarządzać bazą danych realm i platformą Realm. Dzięki Realm Studio możesz otwierać i edytować lokalne i zsynchronizowane Serwery Realm oraz administrować dowolną instancją serwera obiektu Realm. Pobierz go teraz na Mac, Windows lub Linux.
rysunek 9
jak pokazano na rysunku 10 dane faktycznie przechowywane. Możesz się zastanawiaćArticle
IPerson
Klasa również tam, ponieważ w niektórych moich klasach projektu twórz modele osoba i artykuł. Po uruchomieniu aplikacji Realm introspektuje wszystkie klasy w aplikacji i frameworkach i odnajduje te klasy, które podklasa klasy obiektu Realm. Uważa listę tych klas za twój schemat danych, który będzie przechowywany na dysku lub w pamięci.
Rysunek 10
pobieranie obiektu z Realm
proces pobierania wszystkich rekordów użytkownika z Realm ma następujące zadania
otrzymujemy instancję Realm database i może ona rzucić: NSError
jeśli Realm nie mógł zostać zainicjowany. Domyślny realm jest tworzony, gdy wywołamy init()
bez parametru
wywołana metoda objects w bazie danych Realm, która zwróci wszystkie obiekty danego typu zapisane w Realm i zwróci wyniki ze wszystkimi obiektami, jak pokazano na rysunku 11
Wydrukowany obiekt na konsoli, aby sprawdzić, czy dane tam są i łączenie obiektów działa poprawnie
rysunek 11
ściągnęliśmy użytkownika rekord z klucza podstawowego, który jest również indeksowaną właściwością, więc otrzymujemy opcjonalny obiekt User, ponieważ obiekt z tym kluczem podstawowym może nie istnieć. Klucz podstawowy może być Int
lub String
zaleca się użycie String.
unikalnie identyfikuje określone obiekty w bazie danych Realm.Po ustawieniu wartości klucza podstawowego dla określonego obiektu nie można jej nigdy zmienić.
Rysunek 12
jak pokazano filtrowaliśmy za pomocą pewnego predykatu oto lista użytych operatorów
filter → dopasowuje wartości równe
filtruj niewrażliwe wielkości liter → dopasowuje wartości równe ignorowaniu wielkości liter
w {1,2,3} filter → dopasowuje wartość z listy wartości.
filter → pasuje, jeśli wartość firstName zaczyna się od a.
filter → pasuje, jeśli wartość firstName łączy się z li.
predykat z obiektem Passport chcemy filtrować użytkownika, który ma numer paszportu == 'pass1′
predykat z obiektem Todos chcemy filtrować użytkownika, który ma dowolny tdodo zawiera szczegóły == 'Need OT create rxswift blog’
dla zaawansowanych zapytań zaleca się zobaczyćhttps://academy.realm.io/posts/nspredicate-cheatsheet/ to nspredicate Cheatsheet
uwaga: to, co określasz jako „właściwości przejściowe (obliczone)”, Realm odnosi się do „Właściwości ignorowane”. Są to właściwości, które są w większości ignorowane przez Realm, więc nie będą przechowywane w pliku db, mogą być mutowane poza transakcjami zapisu itp.Oznacza to jednak również, że nie korzystają one z wielu możliwości nie ignorowanych właściwości, takich jak zapytania. (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
wyniki na żywo
ostatni temat pobierania z sekcji Realm
zestawy wyników Realm zawsze zwracają najnowsze, aktualne dane. Dane w wynikach nigdy nie są przestarzałe. Oznacza to, że nigdy nie trzeba przeładowywać wyników z dysku lub w jakiś sposób ręcznie odświeżać danych w pamięci.
jak pokazano na rysunku 15 otrzymaliśmy nowego użytkownika i nie pobieraliśmy przy użyciu metody realm.objects
zamiast tego nowo dodany obiekt jest prezentowany na zmiennej users . Jeśli pochodzisz z podstawowego tła danych, musisz ponownie pobrać obiekt ze stosu
Odczyt i zapis może się zdarzyć w różnych miejscach projektu, w różnych wątkach, z różnych procesów lub, podczas korzystania z platformy Realm, z dowolnego miejsca na świecie. Każda klasa w aplikacji może skupić się na logice biznesowej i zapomnieć o pojęciu przestarzałych lub buforowanych danych, ponieważ obiekty Realm są zawsze aktualne.
Modyfikuj obiekt na serwerze
jak pokazano na rysunku 16 modyfikujemy klucz podstawowy i otrzymujemy „klucz podstawowy nie może zostać zmieniony po włożeniu obiektu.”wyjątek, ponieważ nie możemy zaktualizować klucza podstawowego . Z dokumentu Realm klucz podstawowy jest dodawany do Realm, klucz podstawowy nie może być zmieniony. Obejście → Usuń i włóż ponownie obiekt lub zobacz to pytanie w stackoverflow
Rysunek 16
jak pokazano na rysunku 17 nie można modyfikować obiektu pobranego z obszaru poza blokiem transakcji zapisu jeśli spróbujesz zmodyfikować poza tym, otrzymasz wyjątek „’próba modyfikacji obiektu poza transakcją zapisu — wywołaj beginwritetransaction na instancji rlmrealm.”
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
rysunek 18
19
ostatni przykład jest bardzo interesujący wykonaliśmy następujące zadania, aby zaktualizować użytkownika za pomocą Newuser
otrzymujemy użytkownika z jego kluczem podstawowym userId
który jest 1
utworzył nowyUser
z tym samym kluczem podstawowym
w transakcji zapisu wywołujemy add batch metoda update z update = true zaktualizuje Użytkownika posiadającego klucz podstawowy = 1 . 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 łączenie z usuniętymi ustawi ich Właściwość linking na nil. Jeśli obiekty te są połączone z dowolnymi właściwościami listy, są one usuwane z tych list.
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 obiekt realm. Jak pokazano na rysunku realm.isEmpty
zwraca true
rysunek 24
czasami musisz zbudować jakąś hierarchię między obiektami Realm, tak jak zwykle robisz to z klasami SWIFT. Niestety Realm nie obsługuje obecnie dziedziczenia obiektów po wyjęciu z pudełka . Obejście: 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/