Formation PUB900 : Développer une application pour iPhone avec SwiftUI, H-2024 Fonctions obsolètes ou anciennes syntaxes

78.2 ObservableObject, @Published et @StateObject


La macro @Observable n'existe que depuis iOS 17, sorti en septembre 2023.

Auparavant, le mécanisme d'observation nécessitait trois choses :

  • Une classe qui répond au protocole ObservableObject
  • Une ou plusieurs propriétés de cette classe marquées avec @Published
  • Dans la vue qui utilise la classe, une propriété qui observe un objet de cette classe, marquée par @StateObject

Ce mécanisme fonctionne encore mais la macro @Observable est plus simple à utiliser.

Voici un exemple de classe qui définit un objet observable à l'aide de l'ancienne technique.

SwiftUI (avant iOS 17)

class Position: ObservableObject {
  @Published var x: Double = 0.0
  @Published var y: Double = 0.0
  @Published var z: Double = 0.0

  func modifierPosition() {
    ...   // mécanisme pour modifier une ou plusieurs propriétés publiées
  }
}

Et voici un exemple de vue qui doit surveiller un objet de cette classe.

Au même titre qu'une variable d'état, les variables observées forcent le rafraîchissement de la vue dès qu'elles sont modifiées.

SwiftUI (avant iOS 17)

struct ContentView: View {
  @StateObject private var position: Position = Position()   // l'objet est instancié ici

  var body: some View {
    ...
    Text(position.x)   // sera rafraîchi dès que la propriété change dans la classe
  }
}

Prenez note qu'au lieu de @StateObject, il est possible de travailler avec @ObservableObject dans une sous-vue ou encore avec @EnvironmentObject si l'objet a été rendu disponible à tous les descendants.

Initialisation dans le constructeur

Si vous devez passer par le constructeur pour initialiser un objet décoré avec @StateObject, quelques précautions s'imposent sinon, vous obtiendrez un message du genre « Cannot assign to property: '...' is a get-only property ».

D'abord, il faut faire précéder le nom de la propriété par une barre de soulignement. En effet, on travaille ici avec une propriété encapsulée, aussi appelée propriété privée sous-jacente (en anglais : backing property) qui a été créée automatiquement lors de la déclaration de la variable décorée avec @StateObject.

Ensuite, il faut utiliser StateObject(wrappedValue:...) pour faire l'initialisation.

Voici un exemple avec une classe qui se charge d'appeler un API dont l'URL est fourni à l'extérieur de la vue.

SwiftUI (avant iOS 17)

struct ContentView: View {

@StateObject private var appelAPI: AppelAPI  // on ne peut pas instancier l'objet ici puisqu'il nous manque une information


init(chaineURL: String) {
  _appelAPI = StateObject(wrappedValue: AppelAPI(chaineURL: chaineURL))
}

Pour plus d'information

« Migrating from the Observable Object protocol to the Observable macro ». Apple. https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro

« Data Flow in SwiftUI ». Tyler Kirtland. https://blog.rocketinsights.com/data-flow-in-swiftui/

« How to use @ObservedObject to manage state from external objects ». Hacking with Swift. https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-observedobject-to-manage-state-from-external-objects

▼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