@State — qu'est-ce que c'est, objectif et utilisation dans SwiftUI

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

@State est un Property Wrapper dans SwiftUI pour gérer l'état local à l'intérieur d'une seule vue. SwiftUI redessine automatiquement la vue à chaque changement d'une propriété @State, rendant l'interface réactive sans appels de mise à jour manuels. Selon la documentation Apple Developer (2025), @State est recommandé pour les types simples et les structures appartenant à une seule vue. @State est le moyen le plus simple d'ajouter de l'interactivité à une interface SwiftUI.

Points clés

  • @State — Property Wrapper pour l'état local appartenant à une seule vue
  • Mise à jour automatique — SwiftUI réinvoque body lors d'un changement de propriété @State
  • Types simples — @State fonctionne avec String, Int, Bool, enum et les structures
  • Ne pas passer aux vues enfants — utilisez @Binding pour les modifications depuis les composants enfants
  • private — les propriétés @State sont toujours déclarées avec le modificateur private

Qu'est-ce que @State dans SwiftUI ?

@State est un Property Wrapper intégré à SwiftUI qui permet à une vue de stocker et de suivre son propre état. Lorsqu'une valeur @State change, SwiftUI redessine automatiquement la vue en réinvoquant la propriété body. C'est le fondement de la programmation réactive dans SwiftUI : le développeur déclare l'état, et le framework se charge de la synchronisation de l'interface.

@State crée une zone de stockage dans le tas gérée par SwiftUI. Cette zone est persistante — elle survit aux initialisations répétées de la structure de la vue, qui se produisent à chaque rendu. SwiftUI utilise l'identifiant de la vue (généré à partir de sa position dans la hiérarchie) pour lier la propriété @State à une vue spécifique. Grâce à cela, l'état n'est pas réinitialisé lors de la mise à jour de la vue parente.

Une limitation importante : @State est destiné uniquement aux types de valeur (structures, énumérations, primitifs). Pour les types de référence (classes), utilisez @StateObject ou @ObservedObject. Si vous assignez une classe à une propriété @State, SwiftUI ne pourra pas détecter les modifications à l'intérieur de l'objet — seulement le remplacement complet de la référence.

Comment @State fonctionne sous le capot ?

SwiftUI implémente @State via un mécanisme interne de Stockage. Chaque propriété @State obtient une cellule mémoire dédiée stockée dans un conteneur de stockage spécial de la vue. Lorsqu'une écriture dans wrappedValue se produit, SwiftUI notifie son graphe de dépendances via didSet de la nécessité de redessiner.

swift
struct ContentView: View {
    @State private var name: String = "User"
    @State private var isLoggedIn: Bool = false

    var body: some View {
        VStack {
            Text("Bonjour, \(name)")
            Button(isLoggedIn ? "Déconnexion" : "Connexion") {
                isLoggedIn.toggle()
            }
        }
    }
}

Dans l'exemple, il y a deux propriétés @State : name (String) et isLoggedIn (Bool). Lorsque isLoggedIn.toggle() est appelé, SwiftUI marque ContentView comme nécessitant une mise à jour et réinvoque body dans le cycle de rendu suivant. Le point clé : les propriétés @State sont toujours déclarées avec le modificateur private — cela signale que l'état appartient exclusivement à la vue actuelle et ne doit pas être modifié de l'extérieur directement.

Pour observer les changements, SwiftUI utilise CurrentValueSubject de Combine. Chaque propriété @State crée un éditeur caché qui notifie le système à chaque modification. Cela permet à SwiftUI de ne redessiner que l'ensemble minimal nécessaire de vues, évitant les mises à jour complètes de la hiérarchie.

Quand utiliser @State dans un projet

@State est optimal pour les états locaux simples : champs de texte dans la recherche, indicateurs booléens pour les fenêtres modales, interrupteurs de paramètres, compteurs, éléments de liste sélectionnés. Si une valeur n'est utilisée que dans une seule vue et ses composants enfants (via @Binding), @State est le bon choix. Pour les états qui doivent survivre à la fermeture de la vue (par exemple, les données de formulaire), @State fonctionne également tant que la vue reste dans la hiérarchie.

  • Champs de texte — @State pour stocker le texte saisi dans TextField
  • Indicateurs booléens — @State pour afficher/masquer les fenêtres modales et les feuilles
  • Sélection d'éléments — @State pour suivre l'onglet ou la ligne sélectionnée
  • Compteurs — @State pour les valeurs numériques avec incrément/décrément
  • Calculs intermédiaires — @State pour mettre en cache les résultats dans une vue

N'utilisez pas @State pour les états globaux de l'application, la mise en cache de données réseau ou les objets utilisés sur plusieurs écrans. @StateObject et @EnvironmentObject sont conçus à ces fins. De plus, @State n'est pas adapté au stockage de grandes quantités de données — chaque changement redessinera la vue entière.

@State et @Binding : travailler ensemble

@Binding est un pont entre @State dans une vue parente et une vue enfant qui doit modifier cet état. Le parent déclare @State, et le composant enfant reçoit un Binding via la projection $. La modification du Binding dans la vue enfant met automatiquement à jour le @State dans le parent — et vice versa. Cela garantit un flux de données unidirectionnel avec capacité de rétroaction.

swift
struct ParentView: View {
    @State private var text: String = ""

    var body: some View {
        ChildView(text: $text)
    }
}

struct ChildView: View {
    @Binding var text: String

    var body: some View {
        TextField("Enter text", text: $text)
    }
}

Dans le listing, ParentView possède le @State text, et ChildView reçoit $text comme Binding. Le TextField à l'intérieur de ChildView se lie à ce Binding via text: $text. Lorsque l'utilisateur tape dans le TextField, la valeur change dans ChildView via le Binding, ce qui provoque une mise à jour de @State dans ParentView. Les deux vues sont redessinées avec la nouvelle valeur.

Erreurs courantes avec @State

L'erreur la plus courante est d'assigner une classe à une propriété @State. Si vous écrivez @State var model = MyClass(), SwiftUI ne pourra pas suivre les modifications des propriétés à l'intérieur de la classe — seulement le remplacement de l'objet. Pour les classes, utilisez toujours @StateObject. Le deuxième problème courant est de déclarer @State sans le modificateur private, ce qui viole le principe d'encapsulation de l'état.

Passer @State directement à une vue enfant sans $ est une autre erreur typique. Si vous passez TextField(text: text) au lieu de TextField(text: $text), le composant enfant reçoit simplement une chaîne, pas un Binding. Les modifications de texte dans le TextField ne seront pas synchronisées avec le @State du parent. Utilisez toujours la projection $ pour passer Binding.

La troisième erreur est d'avoir plusieurs propriétés @State pour des données liées. Si plusieurs valeurs forment logiquement un tout unique (par exemple, les champs d'un formulaire), combinez-les en une seule structure avec un seul @State. Cela simplifie le passage de l'état aux vues enfants et réduit le nombre de déclencheurs de mise à jour individuels.

Exemples d'utilisation de @State dans SwiftUI

@State est utilisé dans la plupart des projets SwiftUI pour l'interactivité de base. Prenons l'exemple d'un formulaire de connexion où @State gère les champs de texte et l'état de chargement. Ce motif apparaît dans chaque application — des notes simples aux solutions d'entreprise complexes.

swift
struct LoginView: View {
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var isLoading: Bool = false
    @State private var errorMessage: String?

    var body: some View {
        Form {
            TextField("Email", text: $email)
            SecureField("Password", text: $password)
            Button("Connexion") {
                login()
            }.disabled(isLoading)
        }
    }

    private func login() {
        isLoading = true
        // Effectuer une requête réseau
    }
}

Dans l'exemple, il y a quatre propriétés @State : email et password pour les champs du formulaire, isLoading pour l'indication de chargement et errorMessage pour l'affichage des erreurs. Chaque propriété gère indépendamment sa partie de l'interface. Lorsque isLoading change, le bouton est automatiquement désactivé via disabled(isLoading) — sans mise à jour manuelle de l'interface.

Questions fréquentes

Pourquoi @State est-il déclaré avec private ?

@State est conçu pour l'état local d'une vue spécifique. Le modificateur private garantit que les autres composants ne peuvent pas le modifier directement, ce qui briserait l'encapsulation. Pour un accès externe, utilisez la projection $.

@State peut-il contenir un tableau ou un dictionnaire ?

Oui, @State prend en charge les tableaux et les dictionnaires car ce sont des types de valeur. Cependant, lorsqu'un élément d'un tableau change, SwiftUI redessine la vue entière. Pour les grandes listes, @StateObject avec @Published est plus efficace.

Que se passe-t-il si nil est assigné à une propriété @State de type Optional ?

@State fonctionne correctement avec les types Optionals. Lorsque nil est assigné, SwiftUI détecte le changement et redessine la vue. C'est pratique pour des états comme errorMessage: String?, où nil signifie aucune erreur.

Comment @State se comporte-t-il lorsque la vue réapparaît ?

@State conserve la valeur tant que la vue reste dans la hiérarchie. Si la vue est supprimée de la hiérarchie puis ajoutée à nouveau, @State est réinitialisé avec la valeur par défaut. Pour la persistance, utilisez @AppStorage.

Peut-on animer les changements de @State ?

Oui, enveloppez le changement dans withAnimation : withAnimation(.easeInOut) { isExpanded.toggle() }. SwiftUI anime la transition entre l'ancien et le nouvel état de l'interface avec le type d'animation spécifié.

Résumé

  • @State — Property Wrapper pour l'état local d'une seule vue, mettant automatiquement à jour l'interface
  • Fonctionne avec les types simples : String, Int, Bool, ainsi que les structures et énumérations
  • Ne fonctionne pas avec les types de référence (classes) — utilisez @StateObject
  • Toujours private — l'état ne doit pas être modifié de l'extérieur directement
  • Projection $ — crée un Binding pour passer les droits de modification aux vues enfants
  • Plusieurs @State dans une même vue — pratique normale pour des états indépendants
  • withAnimation — permet d'animer les changements des propriétés @State

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