@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 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.
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.
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.
@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.
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.
@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.
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.
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.
@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.
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
@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 $.
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.
@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.
@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.
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é
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.
Lisez aussi