Průvodce databází Realm – Tvorba aplikace Note ve Swiftu pro iOS

Pokud dáváte přednost videím před psanými články, tento článek je psanou verzí videa, které jsem vytvořil. Obsah je totožný.

Toto video je první ze série, která, jak doufám, poslouží k tomu, abyste se naučili používat frameworky a nástroje pro iOS, jako jsou Siri Shortcuts, CloudKit a další. Pokud máte konkrétní framework nebo funkci, kterou byste chtěli, aby se tento seriál zabýval, neváhejte mi napsat na adresu jordanosterbergshadowsystemstech nebo na Twitter @josterbe1.

Obsah

  1. Úvod
  2. Instalace závislostí
  3. Model
  4. Implementace Realm
  5. Závěr

Bez dalších okolků se podíváme na aplikaci, kterou budeme v tomto seriálu vytvářet….

Úvod

Seznam poznámek aplikace
Úprava poznámky jednotlivě

Máme svůj seznam poznámek, a když na některou klepneme, můžeme ji přečíst a začít upravovat, případně smazat. Je to docela jednoduché. Pokud si stáhnete startovací projekt, všimnete si, že poznámky se při přechodu do ovladače NoteDetailController a z něj při klepnutí na poznámku „Návštěva jablečného parku“ nezachovávají. To znamená, že obsah poznámky se neuloží, když ji upravujete.

To je to, co budeme v tomto článku vytvářet pomocí databáze Realm. Realm používám právě asi dva roky a jeho jednoduchost podle mého názoru převyšuje náklady na použití knihovny třetí strany. Ve skutečnosti ji používám v aplikaci, nad kterou trávím většinu svého osobního času při vývoji (viz https://countdowns.download), a to jak v systému MacOS, tak v systému iOS.

Instalace závislostí

Až začneme Realm používat, musíme jej nainstalovat pomocí CocoaPods. CocoaPods, pokud to nevíte, CocoaPods je nástroj pro správu závislostí, který se hojně používá v oblasti iOS. Pokud ještě nemáte CocoaPods na svém Macu nainstalovaný, můžete pro začátek použít příkaz sudo gem install cocoapods. Nyní otevřete složku projektu a také okno Terminálu uvnitř tohoto adresáře.

Napište pod init a poté open Podfile.

Uvnitř nově vytvořeného „Podsouboru“ musíme napsat nějaký text, který bude CocoaPods informovat, jaké knihovny chcete do projektu nainstalovat.

Pod # Pods for NotesApp napište tyto dva řádky:

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

Váš soubor Podfile by měl po napsání těchto řádků vypadat podobně:

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

Teď, když jsme přidali naše závislosti, požádejme CocoaPods, aby je nainstaloval pomocí pod install

Při prvním použití CocoaPods to bude chvíli trvat. Nemějte obavy, CocoaPods právě stahuje některé počáteční komponenty. Nebude se to dít pokaždé, když pod install.

Vaše okno Terminálu bude po dokončení provádění tohoto příkazu vypadat takto:

Okno Terminálu

Pokud jste již otevřeli NotesApp.xcodeproj, zavřete jej. Při použití programu CocoaPods je nutné použít soubor .xcworkspace namísto výchozího souboru .xcodeproj. Otevřete soubor NotesApp.xcworkspace a přejděte na Note.swift.

Model

Tato třída obsahuje náš objekt Note model, který obsahuje několik základních vlastností:

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

Standardní kód modelu, nic zvláštního se zde neděje.

V témže souboru máme také rozšíření našeho objektu Note, které je podtřídou protokolu s názvem Writeable

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

Uvnitř funkcí write a delete si všimněte, že máme vlastnost DataSource. DataSource je generický protokol, který pomáhá, aby modifikace dat na vyšších úrovních našeho kódu byla co nejvíce abstraktní.

Tady je definice protokolu:

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

Pokud nejste obeznámeni s generikou, každá z našich funkcí má parametr T, což v podstatě znamená, že to může být jakýkoli typ objektu. V našem projektu se to příliš nepoužívá, ale dalo by se to rozvinout a dále použít k vytvoření více zdrojů dat s různými omezeními ohledně toho, jaké objekty mohou ukládat.

Náš protokol DataSource implementujeme v NoteDataSource. Ani zde není nic zvláštního, až na jednu drobnost, kterou bych rád poznamenal pro vysvětlení.

Kdykoli store nebo delete objekty, použijeme následující volání 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")}

V podstatě kdykoli je nějaká poznámka uložena nebo odstraněna, informujeme všechny posluchače, že se naše data změnila, aby mohli odpovídajícím způsobem aktualizovat své uživatelské rozhraní.

Když máme všechny modelové soubory a třídy za sebou, začněme implementovat Realm!

Implementace Realm

Při integraci Realm do našeho projektu musíme provést tři kroky:

  1. Vytvoření objektu Realm
  2. Propojení mezi naším objektem Realm a naším primitivním objektem Note
  3. Začněte získávat a upravovat data pomocí Realm

Vytvoření objektu Realm

Tento krok je poměrně jednoduchý. Vytvoříme nový soubor Swift s názvem RealmNote.swift. Uvnitř RealmNote.swift importujeme framework RealmSwift a vytvoříme deklaraci třídy takto:

import RealmSwiftclass RealmNote: Object {}

Budeme podtřídou třídy Realm Object, která nám umožní používat RealmNote ve funkcích databáze Realm.

Nyní přidáme tři vlastnosti, které máme v našem modelu Note:

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

Části @objc dynamic deklarace našich proměnných vystavují naše vlastnosti jazyku Objective-C, ve kterém je napsáno mnoho vrstev systému iOS Realm. Umožňují také Realmu naslouchat změnám našich objektů RealmNote.

Pro dokončení naší třídy překryjte class func primaryKey, který vrací nepovinný řetězec (String?) s hodnotou „identifikátor“. Tím informujeme Realm, že primární klíč RealmNote, tedy způsob jednoznačné identifikace našich objektů, je uložen ve vlastnosti „identifier“.

Po dokončení těchto kroků bude váš RealmNote vypadat takto:

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

To je pro první krok vše.

Přemostění mezi naším objektem Realm a primitivním objektem Note

Máme dva samostatné objekty modelu: Note a RealmNote. RealmNote používáme interně při práci s Realm, abychom udrželi naši modelovou vrstvu oddělenou od našeho uživatelského rozhraní. Díky použití dvou oddělených objektů bychom se mohli v budoucnu od používání Realm v případě potřeby odpoutat.

V souboru RealmNote.swift vytvořte rozšíření RealmNote:

extension RealmNote {}

Nyní uvnitř tohoto rozšíření vytvořte convenience init, který jako jedinou vlastnost přijímá Note. To nám umožní vytvářet objekty RealmNote pomocí objektu Note.

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

Skvěle, a teď, abychom dokončili RealmNote.swift, vytvořte uvnitř rozšíření proměnnou Note, která se inicializuje z objektu RealmNote:

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

Nebojte se, pokud vám Xcode vyhodí chybu ohledně inicializátoru Note, to právě napravíme.

Přejděte na Note.swift, kde se chystáme napsat druhou polovinu našeho můstku. Tento kód je v podstatě stejný jako rozšíření RealmNote.

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

Skvělé, to je druhý krok. Nyní můžeme přistupovat k RealmNote z Note a k Note z RealmNote. To také znamená, že tento kód je naprosto správný:

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

Vtipy stranou, dokončeme naši aplikaci třetím krokem.

Začněte načítat a upravovat data pomocí Realm

Zamíříme do NoteDataSource.swift a import RealmSwift před deklaraci třídy. Než začneme modifikovat, mazat a načítat objekty Realm, potřebujeme instanci databáze Realm. Nahraďte init NoteDataSource tímto:

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

Tím vytvoříte instanci databáze Realm. V produkčním prostředí byste pravděpodobně nechtěli při vytváření instance používat operátor bang (!), protože pokud nebude databáze k dispozici, dojde k pádu aplikace.

Dále upravíme funkci store, která bude skutečně ukládat objekty do naší databáze.

Zápis pomocí Realm je jednoduchý:

try? self.realm.write {}

Uvnitř tohoto bloku kódu můžeme aktualizovat objekty v databázi. Napište toto:

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

Tím se buď vytvoří nový RealmNote v databázi, nebo se aktualizuje stávající, pokud existuje. To je vše! Nyní ukládáme objekty do databáze Realm (volání funkce zápisu poznámky se provádí v NoteDetailController.swift, pokud byste chtěli vidět funkci, která se skutečně používá k provedení tohoto zápisu)

Nyní napíšeme naši funkci delete. Vzhledem ke způsobu, jakým jsme napsali náš můstek (bez konzultace s Realmem, kdykoli vytváříme RealmNote z Note), musíme objekt načíst přímo z databáze pomocí identifikátoru poznámky, nikoli pomocí její vlastnosti realmNote.

Je to jednoduché:

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

Tímto požádáme Realm, aby z databáze načetl objekt RealmNote s identifikátorem neboli primárním klíčem note.identifier.

To může být trochu legrační. Z nějakého důvodu aplikace spadne, pokud na Realm použijeme tradiční funkci write. Jako řešení je tento kód naprosto správný a v podstatě provádí stejnou úlohu jako write:

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

Začneme náš zápis, smažeme objekt a odevzdáme náš zápis.

Tímto jsme vytvořili funkční poznámkovou aplikaci!

Závěr

Doufám, že se vám tento návod, jak používat databázi Realm, líbil. Při jeho tvorbě jsem si užil spoustu legrace a nemohu se dočkat, až budeme tento seriál rozvíjet a časem do naší aplikace přidáme další funkce, jako jsou například zkratky Siri, CloudKit a další. Díky za přečtení.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.