Formation PUB900 : Développer une application pour iPhone avec SwiftUI, H-2024 CRUD avec SwiftData

42.1 Opérations CRUD avec SwiftData (ajouter, modifier ou supprimer des données)


Avec SwiftData, effectuer des opération CRUD (Create, Read, Update, Delete) est un charme.

Dans cette fiche :

Insert

L'insertion de données consiste à instancier un nouvel objet puis à faire appel à modelContext.insert().

Je vous présente ici l'insertion à l'intérieur de ContentView mais cela pourrait avoir lieu dans n'importe quelle autre vue.

Notez que dans ces exemples, on considère que l'enregistrement automatique est activé – ce qui est le cas par défaut – donc il n'y a pas d'appel à save().

SwiftUI

import SwiftData
...

Struct ContentView: View {
  @Environment(\.modelContext) var modelContext
  ...

  var body: some View {
    ...
    Button(action: {
      let item = Item(code: "abc", titre: "Item abc")
      modelContext.insert(item)
      ...
    }) {
      Text("Enregistrer")
    }
    .buttonStyle(.bordered)
    ...
  }
}

Delete

Pour supprimer un enregistrement, il est important d'avoir en main un objet qui a été instancié à partir d'une requête.

La façon la plus traditionnelle consiste à créer le bouton de suppression à même la liste qui affiche les données.

Le traitement consistera à appeler modelContext.delete().

SwiftUI

List(items) { item in
  VStack(alignment: .leading) {
    HStack {
      Text("\(item.code) - \(item.titre)")
      Spacer()
      Button(
        role: .destructive,
        action: {
          modelContext.delete(item)
          ...
      }) {
        Image(systemName: "trash")
      }
    }
  }
}

Confirmation avant suppression

Il est d'usage de demander confirmation avant suppression puisque cette opération est irréversible.

Pour y arriver :

  • Ajouter un confirmationDialog à la vue.
  • L'action du bouton modifiera la valeur d'une variable de session qui gère l'affichage du confirmationDialog. Elle retiendra également une référence à l'item qui doit être supprimé.
  • Le bouton Supprimer du confirmationDialog se chargera de faire le modelContext.delete. Il utilisera la référence à l'item qui a été retenue plus tôt.

Vider une table entière

Pour supprimer tous les enregistrements d'une table, il suffit d'appeler la méthode delete() avec le modèle comme paramètre.

SwiftUI

do {
  try modelContext.delete(model: Item.self)
  ...
} catch {
  print("Impossible de supprimer tous les items.")
}

Update

La mise à jour sera généralement effectuée à partir d'un formulaire qui aura été affiché à partir de la liste d'items. On sera ainsi assurés que c'est le bon enregistrement qui est mis à jour.

Contrairement à l'ajout et à la suppression, il suffit de mettre à jour l'objet pour que les données soient enregistrées dans la base de données.

SwiftUI

Button(
  action: {
    item.nom = nom
    item.titre = titre
    ...
}) {
  Text("Enregistrer")
}

.save() pour que les modifications soient immédiatement disponibles

Par défaut, les modifications au modelContext seront automatiquement réflétées dans la base de données.

L'usager aura l'impression que les données sont enregistrées sur-le-champ. Dans les faits, l'enregistrement aura lieu à des moments précis, par exemple lorsque l'application passe en arrière-plan ou revient au premier-plan ou encore lorsque la boucle courante se termine. Ce délai peut être de quelques fractions de secondes mais s'étire parfois sur une trentaine de secondes.

Il y a des situations où ce délai peut causer des mauvais fonctionnements de l'application.

C'est le cas, par exemple, si on ajoute un enregistrement puis qu'on appelle immédiatement une fonction qui utilise cet enregistrement.

Pour assurer que l'enregistrement soit immédiatement disponible, il faut faire appel à modelContext.save().

Dans cet exemple, le code doit appeler une fonction qui synchronise la base de données locale avec une base de données distante via un service Web.

SwiftUI

let item = Item(code: "abc", titre: "Item abc")
modelContext.insert(item)

do {
   try modelContext.save() // sans ceci, l'item n'est pas encore disponible pour la synchro
} catch {
  print("Impossible d'ajouter l'item: \(error)")
  ...   // mécanisme pour afficher un message à l'usager
}

synchroniserBD()

Erreur « Thread 1: Fatal error: Observation Registrar was not found on Model »

Si vous obtenez l'erreur « Thread 1: Fatal error: Observation Registrar was not found on Model » lors de l'ajout, de la modification ou de la suppresison d'un enregistrement, assurez-vous que le modèle ne répond pas au protocole CustomReflectable.

En effet, il semble y avoir un conflit entre le protocole CustomReflectable et le mécanisme d'observation utilisé par SwiftData.

Pour plus d'information

« Adding and editing persistent data in your app ». Apple. https://developer.apple.com/documentation/swiftdata/adding-and-editing-persistent-data-in-your-app/

« Deleting persistent data from your app ». Apple. https://developer.apple.com/documentation/swiftdata/deleting-persistent-data-from-your-app

« Creating, editing, and deleting model objects ». Hacking with Swift. https://www.hackingwithswift.com/quick-start/swiftdata/creating-editing-and-deleting-model-objects

«  When does SwiftData autosave data?  ». Hacking with Swift. https://www.hackingwithswift.com/quick-start/swiftdata/when-does-swiftdata-autosave-data

« How to save a SwiftData object ». Hacking with Swift. https://www.hackingwithswift.com/quick-start/swiftdata/how-to-save-a-swiftdata-object

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre