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
- Bevezetés
- A függőségek telepítése
- A modell
- A Realm implementálása
- 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
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:
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:
- A Realm objektum létrehozása
- A Realm objektumunk és a primitív Note objektumunk közötti összeköttetés
- 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.