Realm Database Guide – Opbygning af en note-app i Swift til iOS

Hvis du foretrækker videoer frem for skriftlige artikler, er denne artikel en skriftlig version af en video, som jeg har produceret. Indholdet er identisk.

Denne video er den første i en serie, som forhåbentlig skal tjene til at lære dig at bruge iOS-rammer og værktøjer såsom Siri Shortcuts, CloudKit og meget mere. Hvis du har en specifik ramme eller funktion, som du gerne vil have, at denne serie dækker, er du velkommen til at skrive til mig på jordanosterbergshadowsystemstech eller på Twitter @josterbe1.

Indholdsfortegnelse

  1. Indledning
  2. Installation af afhængigheder
  3. Modellen
  4. Implementering af Realm
  5. Konklusion

Så lad os uden videre tage et kig på den applikation, som vi vil bygge i denne serie…

Introduktion

Applikationens liste over noter
Redigering af en note individuelt

Vi har vores liste over noter, og når vi trykker på en, kan vi læse og begynde at redigere eller slette den. Ganske enkelt. Du vil bemærke, hvis du downloader startprojektet, at noterne ikke bliver ved med at eksistere, når du går ind og ud af NoteDetailController, når du trykker på noten “Apple Park Visit”. Det vil sige, at indholdet af noten ikke gemmes, når du redigerer den.

Det er det, vi vil bygge ud i denne artikel, ved hjælp af Realm Database. Jeg har brugt Realm i lige omkring to år, og jeg synes, at dens enkelhed opvejer omkostningerne ved at bruge et 3. parts bibliotek. Faktisk bruger jeg det i den app, som jeg bruger mest af min personlige udviklingstid på (se https://countdowns.download) på både macOS og iOS.

Installation af afhængigheder

For at kunne begynde at bruge Realm skal vi installere det ved hjælp af CocoaPods. CocoaPods, hvis du ikke er klar over det, CocoaPods er et afhængighedsstyringsværktøj, der er meget udbredt inden for iOS-området. Hvis du ikke allerede har CocoaPods installeret på din Mac, kan du bruge kommandoen sudo gem install cocoapods for at komme i gang. Åbn nu projektmappen samt et Terminal-vindue inde i denne mappe.

Typ pod init og derefter open Podfile.

Inden for den nyoprettede “Podfile” skal vi skrive noget tekst, som vil informere CocoaPods om, hvilke biblioteker du ønsker at installere i dit projekt.

Under # Pods for NotesApp skal du skrive disse to linjer:

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

Din Podfile bør se sådan ud, når du har skrevet disse linjer:

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

Nu da vi har tilføjet vores afhængigheder, skal vi bede CocoaPods om at installere dem med pod install

Dette vil tage noget tid, når du bruger CocoaPods første gang. Bare rolig, CocoaPods henter bare nogle indledende komponenter. Dette vil ikke ske hver gang du pod install.

Dit Terminalvindue vil se således ud, når denne kommando er færdig med at blive udført:

Terminalvindue

Hernæst, hvis du allerede har åbnet NotesApp.xcodeproj, skal du lukke ud af det. Når du bruger CocoaPods, skal du bruge .xcworkspace-filen i stedet for standardfilen .xcodeproj. Åbn NotesApp.xcworkspace-filen, og gå til Note.swift.

Modellen

Denne klasse indeholder vores Note-modelobjekt, som indeholder et par grundlæggende egenskaber:

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

Standardmodelkode, der sker ikke noget særligt her.

Vi har også en udvidelse til vores Note-objekt i den samme fil, som underklasses som protokol kaldet Writeable

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

Inden for write og delete-funktionerne vil du bemærke, at vi har en DataSource-egenskab. DataSource er en generisk protokol, der skal hjælpe med at gøre ændring af data så abstrakt på de højere niveauer af vores kode som muligt.

Her er protokollens definition:

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

Hvis du ikke er bekendt med generiske egenskaber, har hver af vores funktioner en T-parameter, hvilket i bund og grund betyder, at det kan være en hvilken som helst type objekt. Dette bruges ikke særlig meget i vores projekt, men det kan udvikles og bruges yderligere til at skabe flere DataSources med forskellige begrænsninger omkring hvilke objekter de kan gemme.

Vi implementerer vores DataSource-protokol i NoteDataSource. Der er heller ikke noget særligt her, bortset fra en lille detalje, som jeg gerne vil bemærke for forklaringens skyld.

Når vi store eller delete-objekter, bruger vi følgende kald til 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")}

Helt grundlæggende, når en note lagres eller slettes, informerer vi eventuelle lyttere om, at vores data er ændret, så de kan opdatere deres brugergrænseflade i overensstemmelse hermed.

Med alle vores modelfiler og klasser ude af vejen, lad os begynde at implementere Realm!

Implementering af Realm

Der er tre trin for at integrere Realm med vores projekt:

  1. Skabelse af Realm-objektet
  2. Brydning mellem vores Realm-objekt og vores primitive Note-objekt
  3. Begynd at hente og ændre data med Realm

Skabelse af Realm-objektet

Dette trin er relativt enkelt. Lad os oprette en ny Swift-fil ved navn RealmNote.swift. Inde i RealmNote.swift importerer du RealmSwift-rammen og opretter en klassedeklaration som følger:

import RealmSwiftclass RealmNote: Object {}

Vi underklasserer Realms Object-klasse, hvilket vil give os mulighed for at bruge RealmNote i Realm-databasefunktioner.

Nu skal vi tilføje de tre egenskaber, som vi har i vores Note-model:

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

De @objc dynamic stykker af vores variabeldeklaration eksponerer vores egenskaber til Objective-C, som mange af iOS-lagene i Realm er skrevet i. Det giver også Realm mulighed for at lytte efter ændringer i vores RealmNote-objekter.

For at afslutte vores klasse skal du overskrive class func primaryKey, som returnerer en valgfri streng (String?) med værdien “identifier”. Dette informerer Realm om, at RealmNotes primære nøgle, en måde at identificere vores objekter entydigt på, er gemt i egenskaben “identifier”.

Når du har gennemført disse trin, vil din RealmNote se således ud:

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

Det var alt for trin et.

Brobygning mellem vores Realm-objekt og vores primitive Note-objekt

Vi har to separate modelobjekter: Note og RealmNote. RealmNote bruges internt, når vi har med Realm at gøre, for at holde vores modellag afkoblet fra vores brugergrænseflade. Ved at bruge to separate objekter kan vi skifte væk fra at bruge Realm i fremtiden, hvis behovet opstår.

I RealmNote.swift-filen opretter du en udvidelse af RealmNote:

extension RealmNote {}

Opret nu en convenience init inde i udvidelsen, som tager imod en Note som sin eneste egenskab. Dette vil give os mulighed for at oprette RealmNote-objekter ved at bruge et Note-objekt.

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

Godt, nu, for at afslutte RealmNote.swift, opretter du en Note-variabel inde i udvidelsen, som initialiseres fra et RealmNote:

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

Bekymre dig ikke, hvis Xcode giver dig en fejl om Notes initialisator, det er vi ved at rette op på.

Kør over til Note.swift, hvor vi nu skal til at skrive den anden halvdel af vores bro. Denne kode er stort set det samme som RealmNotes udvidelse.

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

Godt, det er trin to. Vi kan nu få adgang til en RealmNote fra en Note, og en Note fra en RealmNote. Det betyder også, at denne kode er helt gyldig:

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

Sjov til side, lad os afslutte vores applikation med trin tre.

Begynd at hente og ændre data med Realm

Hovedet ind i NoteDataSource.swift, og import RealmSwift før klassedeklarationen. Før vi ændrer, sletter og henter Realm-objekter, har vi brug for en instans af Realm-databasen. Udskift NoteDataSource‘s init med dette:

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

Dette vil oprette en instans af Realm-databasen. I produktion vil du sandsynligvis ikke bruge operatoren bang (!), når du opretter instansen, fordi din applikation vil gå ned, hvis databasen ikke er tilgængelig.

Næst skal vi redigere store-funktionen for rent faktisk at gemme objekter i vores database.

Skrivning med Realm er enkel:

try? self.realm.write {}

Inden for denne kodeblok kan vi opdatere objekter i databasen. Skriv dette:

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

Dette vil enten oprette et nyt RealmNote i databasen eller opdatere et eksisterende RealmNote, hvis der findes et. Det var det hele! Vi lagrer nu objekter i Realm-databasen (kald af notens skrivefunktion udføres i NoteDetailController.swift, hvis du gerne vil se den funktion, der faktisk bruges til at udføre denne skrivning.)

Nu skal vi skrive vores delete-funktion. På grund af den måde, vi skrev vores bro (uden at konsultere Realm, når vi opretter en RealmNote fra en Note), skal vi hente objektet direkte fra databasen ved hjælp af notens identifikator i stedet for at bruge dens realmNote-egenskab.

Dette er simpelt:

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

Dette beder Realm om at hente et RealmNote-objekt fra databasen med identifikatoren, eller primærnøglen, note.identifier.

Dette kan være en smule funky. Af en eller anden grund går programmet ned, hvis vi bruger den traditionelle write-funktion på Realm. Som en løsning er denne kode helt gyldig og udfører i det væsentlige den samme opgave som write:

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

Vi begynder vores skrivning, vi sletter objektet, og vi bekræfter vores skrivning.

Med det har vi bygget en fungerende noteapplikation!

Konklusion

Jeg håber, at du har haft glæde af denne vejledning i brugen af Realm-databasen. Jeg har haft det meget sjovt at lave den, og jeg kan ikke vente med at udvikle denne serie og tilføje flere funktioner til vores app med tiden, f.eks. Siri-genveje, CloudKit og meget mere. Tak fordi du læste.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.