Realm Database Guide – Jegyzetalkalmazás építése Swiftben iOS-re

Ha jobban szereted a videókat az írott cikkek helyett, ez a cikk egy általam készített videó írott változata. A tartalom megegyezik.

Ez a videó az első egy sorozatban, amely reményeim szerint arra szolgál, hogy megtanítson téged az iOS keretrendszerek és eszközök, például a Siri Shortcuts, a CloudKit és más eszközök használatára. Ha van egy konkrét keretrendszer vagy funkció, amivel szeretnéd, hogy ez a sorozat foglalkozzon, írj nekem bátran a jordanosterbergshadowsystemstech címre, vagy a Twitteren @josterbe1.

Tartalomjegyzék

  1. Bevezetés
  2. A függőségek telepítése
  3. A modell
  4. A Realm implementálása
  5. Következtetés

Minden további nélkül nézzük meg az alkalmazást, amelyet ebben a sorozatban fogunk felépíteni…

Bevezetés

Az alkalmazás jegyzetlistája
Egy jegyzet egyenként történő szerkesztése

Megvan a jegyzetlistánk, és ha rákattintunk az egyikre, akkor elolvashatjuk és elkezdhetjük szerkeszteni, vagy törölhetjük. Elég egyszerű. Ha letölti a kezdőprojektet, észre fogja venni, hogy a jegyzetek nem maradnak fenn, amikor a NoteDetailControllerbe lépünk be és ki, amikor az “Apple Park látogatás” jegyzetre koppintunk. Vagyis a jegyzet tartalma nem menti el, amikor szerkeszti.

Ezt fogjuk kiépíteni ebben a cikkben, a Realm adatbázis segítségével. Éppen két éve használom a Realmot, és úgy találom, hogy az egyszerűsége felülmúlja egy harmadik féltől származó könyvtár használatának költségeit. Valójában abban az alkalmazásban használom, amellyel a legtöbb személyes fejlesztési időmet töltöm (lásd https://countdowns.download), mind macOS-en, mind iOS-en.

A függőségek telepítése

Hogy elkezdhessük használni a Realmot, telepítenünk kell a CocoaPods segítségével. A CocoaPods, ha nem tudnád, a CocoaPods egy függőségkezelő eszköz, amelyet széles körben használnak az iOS térben. Ha még nincs telepítve a CocoaPods a Mac-en, akkor a sudo gem install cocoapods parancsot használhatja a kezdéshez. Most nyissuk meg a projekt mappát, valamint egy Terminal ablakot a könyvtáron belül.

Tippeljük be a pod init, majd open Podfile.

A frissen létrehozott “Podfile” belsejébe írnunk kell néhány szöveget, amely tájékoztatja a CocoaPods-t, hogy milyen könyvtárakat szeretnénk telepíteni a projektünkbe.

A # Pods for NotesApp alá írjuk ezt a két sort:

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

A Podfile-unknak ehhez hasonlóan kell kinéznie, miután megírtuk ezeket a sorokat:

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

Most, hogy hozzáadtuk a függőségeket, kérjük meg a CocoaPodsot, hogy telepítse őket a pod install

Ez némi időt vesz igénybe, amikor először használjuk a CocoaPodsot. Ne aggódjon, a CocoaPods csak néhány kezdeti komponenst tölt le. Ez nem fog minden alkalommal megtörténni, amikor pod install.

A Terminál ablakod így fog kinézni, amint ez a parancs befejezi a végrehajtást:

Terminál ablak

Ezután, ha már megnyitottad a NotesApp.xcodeproj, zárd ki belőle. A CocoaPods használatakor az alapértelmezett .xcodeproj fájl helyett a .xcworkspace fájlt kell használni. Nyisd meg a NotesApp.xcworkspace fájlt, és menj a Note.swift címre.

The Model

Ez az osztály tartalmazza a Note modell objektumunkat, amely néhány alapvető tulajdonságot tartalmaz:

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 }}

Szokásos modellkód, itt semmi különös nem történik.

Egy bővítménye is van a Note objektumunknak ugyanebben a fájlban, amely protokollként alosztályozódik Writeable

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

A write és delete függvények között észrevehetjük, hogy van egy DataSource tulajdonságunk. A DataSource egy generikus protokoll, amely segít abban, hogy az adatok módosítása a lehető legabsztraktabb legyen a kódunk magasabb szintjein.

Itt a protokoll definíciója:

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

Ha nem ismered a generikát, minden függvényünknek van egy T paramétere, ami lényegében azt jelenti, hogy bármilyen típusú objektum lehet. Ezt nem nagyon használjuk a projektünkben, de tovább lehetne fejleszteni és tovább lehetne használni, hogy több DataSource-t hozzunk létre különböző korlátozásokkal arra vonatkozóan, hogy milyen objektumokat tárolhatnak.

A DataSource protokollunkat a NoteDataSource-ben valósítjuk meg. Itt sincs semmi különös, eltekintve egy apróságtól, amit a magyarázat kedvéért megjegyeznék.

Amikor store vagy delete objektumokat használunk, a következő hívást használjuk a NotificationCenter-nek:

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")}

Lényegében, amikor bármilyen jegyzetet tárolunk vagy törölünk, értesítünk minden hallgatót, hogy az adataink megváltoztak, így ők ennek megfelelően frissíthetik a felhasználói felületüket.

Mivel minden modellfájlunk és osztályunk kikerült az útból, kezdjük el a Realm implementálását!

A Realm implementálása

Három lépésből áll a Realm integrálása a projektünkbe:

  1. A Realm objektum létrehozása
  2. A Realm objektumunk és a primitív Note objektumunk közötti összeköttetés
  3. Adatok lekérdezésének és módosításának megkezdése a Realm segítségével

A Realm objektum létrehozása

Ez a lépés viszonylag egyszerű. Hozzunk létre egy új Swift fájlt RealmNote.swift néven. A RealmNote.swift belsejében importáljuk a RealmSwift keretrendszert, és hozzunk létre egy osztálydeklarációt a következőképpen:

import RealmSwiftclass RealmNote: Object {}

A Realm Object osztályát fogjuk alosztályozni, ami lehetővé teszi számunkra, hogy RealmNote a Realm adatbázisfüggvényeiben használjuk.

Most adjuk hozzá a három tulajdonságot, amelyekkel a Note modellünkben rendelkezünk:

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

A változó deklarációnk @objc dynamic darabjai kiteszik a tulajdonságainkat az Objective-C-nek, amelyben a Realm sok iOS rétegét írják. Emellett lehetővé teszi a Realm számára, hogy figyeljen a RealmNote objektumaink változásaira.

Az osztályunk befejezéséhez írjuk felül a class func primaryKey-t, amely egy opcionális stringet (String?) ad vissza az “azonosító” értékkel. Ez tájékoztatja a Realmot, hogy a RealmNote elsődleges kulcsát, az objektumaink egyedi azonosításának módját, az “identifier” tulajdonságban tárolja.

Amikor ezeket a lépéseket elvégeztük, a RealmNote így fog kinézni:

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" }}

Ez volt az első lépés.

Hídépítés a Realm objektumunk és a primitív Note objektumunk között

Két külön modellobjektumunk van: Note és RealmNote. A RealmNote-ot belsőleg használjuk, amikor a Realmmal foglalkozunk, annak érdekében, hogy a modellrétegünk függetlenítve maradjon a felhasználói felületünktől. A két különálló objektum használatával a jövőben el tudunk váltani a Realm használatától, ha szükségessé válik.

A RealmNote.swift fájlban hozzunk létre egy RealmNote kiterjesztést:

extension RealmNote {}

Most hozzunk létre egy convenience init-et a kiterjesztésen belül, amely egyetlen tulajdonságként egy Note-et vesz fel. Ez lehetővé teszi számunkra, hogy RealmNote objektumokat hozzunk létre egy Note objektum segítségével.

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

Klassz, most, hogy befejezzük a RealmNote.swift-t, hozzunk létre egy Note változót a kiterjesztésen belül, amely egy RealmNote-ből inicializálódik:

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

Ne aggódj, ha az Xcode hibát ad a Note inicializálójáról, ezt mindjárt kijavítjuk.

Lépjünk át a Note.swift-be, ahol a híd másik felét fogjuk megírni. Ez a kód lényegében ugyanaz, mint a RealmNote kiterjesztése.

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

Klassz, ez a második lépés. Most már hozzáférhetünk egy RealmNote-hez egy Note-ből, és egy Note-hez egy RealmNote-ből. Ez azt is jelenti, hogy ez a kód tökéletesen érvényes:

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

A viccet félretéve, fejezzük be alkalmazásunkat a harmadik lépéssel.

Kezdjük el az adatok lekérdezését és módosítását a Realm

Kezdjük el a NoteDataSource.swift, és az import RealmSwift osztálydeklaráció előtt. Mielőtt módosítanánk, törölnénk és lekérdeznénk Realm objektumokat, szükségünk van a Realm adatbázis egy példányára. Cseréljük ki a NoteDataSource init-et erre:

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

Ezzel létrehozzuk a Realm adatbázis egy példányát. Termelésben valószínűleg nem szeretnénk a bang (!) operátort használni a példány létrehozásakor, mert az alkalmazásunk összeomlik, ha az adatbázis nem elérhető.

A következőkben szerkesszük meg a store függvényt, hogy ténylegesen objektumokat tároljunk az adatbázisunkban.

A Realmmal való írás egyszerű:

try? self.realm.write {}

A kódblokkon belül frissíthetjük az objektumokat az adatbázisban. Írjuk ezt:

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

Ez vagy egy új RealmNote-t hoz létre az adatbázisban, vagy frissít egy meglévőt, ha van ilyen. Ennyi! Most már objektumokat tárolunk a Realm adatbázisban (a jegyzet írási függvényének meghívása a NoteDetailController.swift-ben történik, ha szeretnéd látni a függvényt, amely valójában ezt az írást végzi)

Most, írjuk meg a delete függvényünket. Mivel a hídunkat úgy írtuk meg (a Realm megkérdezése nélkül, amikor egy RealmNote-et hozunk létre egy Note-ből), az objektumot közvetlenül az adatbázisból kell lekérnünk a jegyzet azonosítójával, nem pedig a realmNote tulajdonságával.

Ez egyszerű:

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

Ez arra kéri a Realmot, hogy kérjen le egy RealmNote objektumot az adatbázisból, a note.identifier azonosítójával vagy elsődleges kulcsával.

Ez egy kicsit funky lehet. Valamilyen oknál fogva az alkalmazás összeomlik, ha a hagyományos write függvényt használjuk a Realm-on. Kerülő megoldásként ez a kód tökéletesen érvényes, és lényegében ugyanazt a feladatot hajtja végre, mint a write:

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

Megkezdjük az írást, töröljük az objektumot, és rögzítjük az írást.

Ezzel egy működő jegyzetalkalmazást építettünk!

Összegzés

Remélem, tetszett ez a bemutató a Realm adatbázis használatáról. Nagyon jól szórakoztam az elkészítésén, és alig várom, hogy továbbfejlesszük ezt a sorozatot, és idővel további funkciókkal bővítsük az alkalmazásunkat, például a Siri parancsikonokkal, a CloudKit-tel és még sok mással. Köszönöm az olvasást.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.