@ObservedObject : qu'est-ce que c'est, comment ça marche et exemples

Auteur : IT Sectr Publié le : 2026-06-19 Temps de lecture : 7 min

@ObservedObject est un Property Wrapper dans SwiftUI pour observer une instance ObservableObject passée de l'extérieur. Contrairement à @StateObject, @ObservedObject ne crée pas d'objet — il s'abonne aux changements d'un objet déjà existant. Selon la Documentation Développeur Apple (2025), @ObservedObject est utilisé dans les vues enfants qui doivent suivre les données appartenant au parent. @ObservedObject fournit une connexion réactive sans gérer le cycle de vie de l'objet.

Points clés

  • @ObservedObject — Property Wrapper pour observer ObservableObject sans possession
  • Sans création — l'objet est passé depuis la vue parent ou l'environnement
  • @Published — propriétés dans ObservableObject dont SwiftUI suit les changements
  • Réaffichage — quand une propriété @Published change, SwiftUI met à jour toutes les vues abonnées
  • Ne pas confondre avec @StateObject — @ObservedObject ne garantit pas une instance unique

Qu'est-ce que @ObservedObject dans SwiftUI ?

@ObservedObject est un Property Wrapper qui abonne une vue aux changements d'un ObservableObject. ObservableObject est un protocole du framework Combine qui nécessite l'implémentation d'un publisher objectWillChange. Lorsqu'une propriété marquée @Published change à l'intérieur de l'ObservedObject, le publisher envoie un signal et SwiftUI réaffiche toutes les vues abonnées via @ObservedObject.

La caractéristique principale de @ObservedObject est l'absence de possession. La vue n'est pas responsable de la création ou de la destruction de l'objet. L'objet est créé dans la vue parent (via @StateObject) ou injecté via @EnvironmentObject. La vue enfant observe seulement les changements et reçoit les mises à jour. Si l'objet est remplacé dans le parent, @ObservedObject bascule vers la nouvelle instance.

@ObservedObject est adapté aux scénarios de partage de données : modèle utilisateur, paramètres communs, état de connexion au serveur. Lorsque plusieurs vues à différents niveaux hiérarchiques doivent afficher les mêmes données, @ObservedObject dans chaque vue crée des abonnements indépendants mais cohérents vers une source unique.

@ObservedObject vs @StateObject : différences clés

La différence entre @ObservedObject et @StateObject est l'un des sujets les plus courants dans les entretiens SwiftUI. La règle principale : @StateObject crée et possède l'objet, @ObservedObject observe un objet déjà existant. Enfreindre cette règle entraîne une perte de données inattendue ou une double initialisation.

Caractéristique@StateObject@ObservedObject
Création d'objetOui, à l'initialisation de la vueNon, reçoit un objet prêt
PossessionVue actuelleComposant parent
Instance uniqueOui, pour tout le cycle de vieNon, peut être remplacée
Recréation au renduNon, persistéeDépend du parent
Où utiliserVue racine propriétaireVues enfants

@StateObject garantit que l'objet est créé une fois et survit aux initialisations répétées de la structure de la vue. @ObservedObject reçoit l'objet de l'extérieur et est recréé à chaque initialisation de la structure parente. Si le parent utilise @StateObject pour l'objet, les vues enfants peuvent appliquer @ObservedObject en toute sécurité — l'objet sera unique dans toute la hiérarchie.

Comment @ObservedObject suit les changements

Le mécanisme de suivi de @ObservedObject est basé sur Combine et le protocole ObservableObject. Lors de l'initialisation, SwiftUI appelle le publisher objectWillChange — l'objet doit émettre un signal avant de modifier une propriété @Published. Combine transmet le signal au graphe de dépendances de SwiftUI, qui marque toutes les vues dépendantes comme nécessitant une mise à jour. Cela se produit de manière synchrone avant que la valeur ne change.

swift
class WeatherService: ObservableObject {
    @Published var temperature: Double = 22.0
    @Published var city: String = "Moscow"
}

struct WeatherView: View {
    @ObservedObject var weather: WeatherService

    var body: some View {
        VStack {
            Text("\(weather.city)")
            Text("\(weather.temperature)°C")
        }
    }
}

Dans l'exemple, WeatherService est un ObservableObject avec deux propriétés @Published. WeatherView déclare @ObservedObject var weather: WeatherService, recevant l'instance du parent. Lorsque temperature change, objectWillChange se déclenche avant de définir la nouvelle valeur, SwiftUI réaffiche WeatherView et la température actuelle s'affiche. L'abonnement est géré automatiquement par SwiftUI — le développeur n'a pas besoin d'appeler sink ou dispose.

Modèles d'utilisation de @ObservedObject

Le premier modèle est le passage d'un modèle via l'initialiseur. Le parent crée un ObservableObject via @StateObject et le passe aux vues enfants en tant que @ObservedObject. C'est un transfert de données hiérarchique standard où la vue racine gère le cycle de vie du modèle et tous les composants imbriqués s'abonnent aux changements.

Le deuxième modèle est EnvironmentObject, une version globale de @ObservedObject via l'environnement SwiftUI. L'objet est injecté au niveau de la scène ou de la vue racine et est automatiquement disponible pour tous les composants enfants sans passage explicite par les initialiseurs. Dans la vue enfant, @EnvironmentObject fonctionne de manière similaire à @ObservedObject mais reçoit l'objet de l'environnement.

Le troisième modèle est la composition de plusieurs ObservableObject. Dans les applications complexes, une vue peut observer plusieurs objets : @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Cela sépare les responsabilités entre les services et maintient la testabilité de chaque composant.

swift
struct DashboardView: View {
    @ObservedObject var user: UserViewModel
    @ObservedObject var network: NetworkMonitor

    var body: some View {
        VStack {
            Text("Welcome, \(user.name)")
            HStack {
                Circle()
                    .fill(network.isConnected ? Color.green : Color.red)
                    .frame(width: 10, height: 10)
            }
        }
    }
}

DashboardView observe UserViewModel et NetworkMonitor. Chaque objet gère son propre domaine de données et notifie indépendamment la vue des changements. Si le réseau se déconnecte, NetworkMonitor modifie isConnected et SwiftUI réaffiche DashboardView, mettant à jour la couleur de l'indicateur. La composition d'ObservableObject est la méthode préférée pour organiser les données dans les applications SwiftUI.

@Published : le lien entre ObservableObject et SwiftUI

@Published est un Property Wrapper de Combine qui ajoute automatiquement un publisher à une propriété dans ObservableObject. Lorsqu'une propriété @Published change, Combine génère un événement via le publisher objectWillChange. SwiftUI s'abonne à ce publisher lors de l'utilisation de @ObservedObject ou @StateObject et réaffiche la vue à chaque nouvelle valeur.

@Published prend en charge tous les types, y compris les optionnels, les collections et les structures personnalisées. Cependant, pour les collections (tableaux, dictionnaires), SwiftUI ne suit que le remplacement de la référence, pas la mutation du contenu. Pour détecter l'ajout ou la suppression d'un élément, vous devez réaffecter l'ensemble de la collection ou utiliser ObservableObject avec objectWillChange.send() manuel.

Un détail important : @Published doit être utilisé uniquement à l'intérieur d'une classe implémentant ObservableObject. Utiliser @Published en dehors d'ObservableObject provoquera une erreur de compilation. De plus, @Published ne peut pas être appliqué aux propriétés d'initialisation paresseuse (lazy var) ni aux propriétés calculées.

Erreurs courantes avec @ObservedObject

L'erreur la plus critique est d'utiliser @ObservedObject pour créer un objet. Si vous écrivez @ObservedObject var model = UserViewModel() dans la vue parent, chaque rendu créera une nouvelle instance de UserViewModel. Les données seront perdues et les abonnements @Published seront recréés. Utilisez toujours @StateObject pour la création et @ObservedObject uniquement pour recevoir un objet déjà prêt.

La deuxième erreur est la modification des propriétés @Published en dehors du thread principal. ObservableObject utilise Combine, qui nécessite l'envoi des modifications sur le thread principal (main actor). Si vous modifiez @Published dans une file d'attente en arrière-plan, SwiftUI pourrait réafficher la vue à un moment inapproprié, provoquant des conditions de concurrence. Utilisez DispatchQueue.main.async ou @MainActor pour les mises à jour.

Le troisième problème est celui des mises à jour cycliques. Si un changement @Published déclenche des effets secondaires qui modifient à nouveau @Published, une boucle infinie de réaffichage se produit. La solution : utiliser des drapeaux de protection (isUpdating) ou séparer la logique sur différents ObservableObject avec des limites de responsabilité claires.

Foire aux questions

@ObservedObject peut-il être optionnel ?

Oui, SwiftUI prend en charge @ObservedObject var model: UserViewModel?. Cependant, la vue ne s'abonnera pas aux changements tant que l'objet est nil. Lorsqu'une valeur est assignée, l'abonnement s'active automatiquement.

Quelle est la différence entre @ObservedObject et @EnvironmentObject ?

@ObservedObject reçoit l'objet via l'initialiseur, @EnvironmentObject via l'environnement SwiftUI. @EnvironmentObject ne nécessite pas de passage explicite par les constructeurs, mais l'objet doit être injecté au niveau supérieur de la hiérarchie.

Comment notifier manuellement SwiftUI d'un changement d'ObservableObject ?

Appelez objectWillChange.send() avant de modifier la propriété. C'est utile lorsque @Published n'est pas approprié (par exemple, pour les propriétés calculées ou les opérations sur les collections où vous devez signaler le changement avant la mutation).

Pourquoi @ObservedObject ne réaffiche-t-il pas la vue lors d'un changement dans un tableau ?

@ObservedObject et @Published suivent le remplacement de la référence, pas la mutation du contenu de la collection. Pour déclencher un réaffichage, vous devez réaffecter le tableau : items.append(newItem) → items = items ou utiliser objectWillChange.send() avant la mutation.

Peut-on utiliser @ObservedObject dans une structure qui n'implémente pas View ?

Non, @ObservedObject est un Property Wrapper de SwiftUI disponible uniquement dans les types qui implémentent le protocole View. Pour les structures ordinaires, utilisez Combine directement avec ObservableObjectPublisher.

Résumé

  • @ObservedObject — Property Wrapper pour observer ObservableObject sans possession
  • @StateObject — crée l'objet, @ObservedObject — observe un existant
  • @Published — publisher automatique pour les propriétés ObservableObject
  • Abonnement — SwiftUI gère automatiquement l'abonnement Combine lors de l'utilisation de @ObservedObject
  • Composition — une vue peut observer plusieurs ObservableObject simultanément
  • Main actor — les propriétés @Published doivent être modifiées uniquement sur le thread principal
  • EnvironmentObject — une alternative à @ObservedObject pour le passage implicite via l'environnement

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi