Guide de la base de données Realm – Construire une application Note en Swift pour iOS

Si vous préférez les vidéos aux articles écrits, cet article est une version écrite d’une vidéo que j’ai produite. Le contenu est identique.

Cette vidéo est la première d’une série qui, je l’espère, servira à vous apprendre à utiliser les frameworks et outils iOS tels que les raccourcis Siri, CloudKit, et plus encore. Si vous avez un framework ou une fonctionnalité spécifique que vous aimeriez voir couvrir par cette série, n’hésitez pas à m’écrire à jordanosterbergshadowsystemstech, ou sur Twitter @josterbe1.

Table des matières

  1. Introduction
  2. Installation des dépendances
  3. Le modèle
  4. Implémentation de Realm
  5. Conclusion

Sans plus attendre, jetons un coup d’œil à l’application que nous allons construire dans cette série….

Introduction

La liste des notes de l'application
Édition d'une note individuellement

Nous avons notre liste de notes, et lorsque nous tapons sur l’une d’entre elles, nous pouvons la lire et commencer à l’éditer, ou la supprimer. C’est assez simple. Vous remarquerez, si vous téléchargez le projet de démarrage, que les notes ne persistent pas lorsque vous entrez et sortez du NoteDetailController en tapant sur la note « Apple Park Visit ». C’est-à-dire que le contenu de la note ne s’enregistre pas lorsque vous la modifiez.

C’est ce que nous allons construire dans cet article, en utilisant la base de données Realm. J’utilise Realm depuis à peu près deux ans, et je trouve que sa simplicité l’emporte sur le coût de l’utilisation d’une bibliothèque tierce. En fait, je l’utilise dans l’application sur laquelle je passe la plupart de mon temps de développement personnel (voir https://countdowns.download) sur macOS et iOS.

Installation des dépendances

Pour commencer à utiliser Realm, nous devons l’installer en utilisant CocoaPods. CocoaPods, si vous ne le savez pas, CocoaPods est un outil de gestion des dépendances qui est largement utilisé dans l’espace iOS. Si vous n’avez pas déjà installé CocoaPods sur votre Mac, vous pouvez utiliser la commande sudo gem install cocoapods pour commencer. Maintenant, ouvrez le dossier du projet, ainsi qu’une fenêtre Terminal à l’intérieur de ce répertoire.

Tapez pod init, puis open Podfile.

À l’intérieur du « Podfile » nouvellement créé, nous devons écrire un texte qui informera CocoaPods des bibliothèques que vous souhaitez installer dans votre projet.

Au-dessous de # Pods for NotesApp, écrivez ces deux lignes :

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

Votre Podfile devrait ressembler à ceci après avoir écrit ces lignes :

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

Maintenant que nous avons ajouté nos dépendances, demandons à CocoaPods de les installer avec pod install

Cela prendra un certain temps lorsque vous utiliserez CocoaPods pour la première fois. Ne vous inquiétez pas, CocoaPods est juste en train de télécharger quelques composants initiaux. Cela ne se produira pas chaque fois que vous pod install.

Votre fenêtre de terminal ressemblera à ceci une fois que cette commande aura fini de s’exécuter :

Fenêtre de terminal

Après cela, si vous avez déjà ouvert le NotesApp.xcodeproj, fermez-le. Lorsque vous utilisez CocoaPods, vous devez utiliser le fichier .xcworkspace au lieu du fichier .xcodeproj par défaut. Ouvrez le fichier NotesApp.xcworkspace et dirigez-vous vers Note.swift.

Le modèle

Cette classe contient notre objet modèle Note, qui contient quelques propriétés de base :

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

Code standard du modèle, rien de spécial ne se passe ici.

Nous avons également une extension à notre objet Note dans le même fichier, qui se sous-classe en tant que protocole appelé Writeable

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

À l’intérieur des fonctions write et delete, vous remarquerez que nous avons une propriété DataSource. DataSource est un protocole générique pour aider à rendre la modification des données aussi abstraite que possible aux niveaux supérieurs de notre code.

Voici la définition du protocole :

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

Si vous n’êtes pas familier avec les génériques, chacune de nos fonctions a un paramètre T qui signifie essentiellement qu’il peut être n’importe quel type d’objet. Ce n’est pas très utilisé dans notre projet, mais il pourrait être évolué et utilisé plus loin pour créer plusieurs DataSources avec différentes contraintes autour des objets qu’ils peuvent stocker.

Nous mettons en œuvre notre protocole DataSource dans NoteDataSource. Il n’y a rien de spécial ici non plus, à part un petit détail que j’aimerais noter pour l’explication.

Chaque fois que nous store ou delete objets, nous utilisons l’appel suivant à 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")}

Essentiellement, chaque fois qu’une note est stockée ou supprimée, nous informons les auditeurs que nos données ont changé, afin qu’ils puissent mettre à jour leur interface utilisateur en conséquence.

Avec tous nos fichiers de modèle et nos classes hors du chemin, commençons à implémenter Realm !

Mise en œuvre de Realm

Il y a trois étapes pour intégrer Realm à notre projet :

  1. Création de l’objet Realm
  2. Pontage entre notre objet Realm et notre objet primitif Note
  3. Commencer à récupérer et modifier les données avec Realm

Création de l’objet Realm

Cette étape est relativement simple. Créons un nouveau fichier Swift appelé RealmNote.swift. A l’intérieur de RealmNote.swift, importez le framework RealmSwift et créez une déclaration de classe comme suit :

import RealmSwiftclass RealmNote: Object {}

Nous allons sous-classer la classe Object de Realm qui nous permettra d’utiliser RealmNote dans les fonctions de la base de données Realm.

Maintenant, ajoutez les trois propriétés que nous avons dans notre modèle Note:

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

Les morceaux @objc dynamic de notre déclaration de variable exposent nos propriétés à l’Objective-C, dans lequel de nombreuses couches iOS de Realm sont écrites. Cela permet également à Realm d’écouter les changements apportés à nos objets RealmNote.

Pour terminer notre classe, surchargez la class func primaryKey, qui renvoie une chaîne optionnelle (String?) avec la valeur « identifiant ». Cela informe Realm que la clé primaire de RealmNote, une façon d’identifier de façon unique nos objets, est stockée dans la propriété « identifier ».

Une fois que vous avez terminé ces étapes, votre RealmNote ressemblera à ceci:

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

C’est tout pour la première étape.

Pont entre notre objet Realm et notre objet Note primitif

Nous avons deux objets modèles séparés : Note et RealmNote. RealmNote est utilisé en interne lors du traitement de Realm, afin de garder notre couche de modèle découplée de notre interface utilisateur. En utilisant deux objets séparés, nous pourrions nous passer de l’utilisation de Realm à l’avenir si le besoin s’en fait sentir.

Dans le fichier RealmNote.swift, créez une extension de RealmNote:

extension RealmNote {}

Maintenant, créez un convenience init à l’intérieur de l’extension qui prend un Note comme seule propriété. Cela nous permettra de créer des objets RealmNote en utilisant un objet Note.

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

Génial, maintenant, pour terminer RealmNote.swift, créez une variable Note à l’intérieur de l’extension qui s’initialise à partir d’un RealmNote:

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

Ne vous inquiétez pas si Xcode vous donne une erreur à propos de l’initialisateur de Note, nous allons corriger cela.

Passez à Note.swift, où nous sommes sur le point d’écrire l’autre moitié de notre pont. Ce code est essentiellement la même chose que l’extension de 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) }}

Génial, c’est la deuxième étape. Nous pouvons maintenant accéder à un RealmNote depuis un Note, et à un Note depuis un RealmNote. Cela signifie également que ce code est parfaitement valide :

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

Parenthèse de plaisanterie, terminons notre application par l’étape trois.

Commencez à récupérer et à modifier des données avec Realm

Partez dans NoteDataSource.swift, et import RealmSwift avant la déclaration de classe. Avant de modifier, supprimer et récupérer des objets Realm, nous avons besoin d’une instance de la base de données Realm. Remplacez le init de NoteDataSource par ceci:

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

Cela créera une instance de la base de données Realm. En production, vous ne voudriez probablement pas utiliser l’opérateur bang ( !) lors de la création de l’instance car votre application se plantera si la base de données n’est pas disponible.

Puis, éditons la fonction store pour stocker réellement des objets dans notre base de données.

Écrire avec Realm est simple:

try? self.realm.write {}

À l’intérieur de ce bloc de code, nous pouvons mettre à jour les objets dans la base de données. Ecrivez ceci:

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

Cela va soit créer un nouveau RealmNote dans la base de données, soit mettre à jour un RealmNote existant s’il existe. C’est tout ! Nous stockons maintenant des objets dans la base de données Realm (la fonction d’écriture de la note d’appel est effectuée dans NoteDetailController.swift si vous souhaitez voir la fonction qui est réellement utilisée pour effectuer cette écriture.)

Maintenant, écrivons notre fonction delete. En raison de la façon dont nous avons écrit notre pont (sans consulter Realm chaque fois que nous créons un RealmNote à partir d’un Note), nous devons aller chercher l’objet directement dans la base de données en utilisant l’identifiant de la note plutôt qu’en utilisant sa propriété realmNote.

C’est simple:

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

Cela demande à Realm de récupérer un objet RealmNote de la base de données, avec l’identifiant, ou clé primaire, de note.identifier.

Cela peut être un peu funky. Pour une raison quelconque, l’application se plante si nous utilisons la fonction traditionnelle write sur Realm. Comme solution de rechange, ce code est parfaitement valide et effectue essentiellement la même tâche que write:

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

Nous commençons notre écriture, nous supprimons l’objet et nous validons notre écriture.

Avec cela, nous avons construit une application de note fonctionnelle!

Conclusion

J’espère que vous avez apprécié ce tutoriel sur la façon d’utiliser la base de données Realm. J’ai eu beaucoup de plaisir à le réaliser et j’ai hâte de faire évoluer cette série et d’ajouter d’autres fonctionnalités à notre application au fil du temps, comme les raccourcis Siri, CloudKit, et plus encore. Merci de votre lecture.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.