@Environment dans SwiftUI est un property wrapper permettant de lire les valeurs de l’environnement système, distribuées automatiquement dans la hiérarchie des Views. Le composant donne accès au schéma de couleurs, aux paramètres régionaux, à la taille de police, à managedObjectContext et à des dizaines d’autres paramètres système. Selon la Documentation Apple Developer (2025), @Environment garantit que toute modification d’une valeur d’environnement déclenche un redessin de toutes les Views abonnées, assurant des mises à jour réactives de l’interface sans appels manuels.
Points clés
@Environment est un property wrapper SwiftUI conçu pour lire les valeurs de l’environnement système. L’environnement est un conteneur hiérarchique de valeurs que SwiftUI distribue automatiquement des Views parentes aux Views enfants. Chaque valeur d’environnement est identifiée par une clé — un type conforme au protocole EnvironmentKey.
Le mécanisme d’environnement ressemble à l’injection de dépendances au niveau du framework : le système fournit un ensemble prédéfini de valeurs — schéma de couleurs (clair/foncé), paramètres régionaux, taille de police, managedObjectContext pour Core Data, dismiss pour fermer les écrans, et bien d’autres. Une View qui déclare @Environment avec une clé spécifique reçoit automatiquement la valeur actuelle et se redessine lorsqu’elle change.
L’architecture de l’environnement SwiftUI est basée sur le protocole EnvironmentValues — une structure contenant toutes les valeurs système. Chaque valeur est stockée comme une propriété de cette structure avec getter et setter. @Environment utilise un key path pour accéder à une propriété spécifique : @Environment(\.colorScheme) — accès au schéma de couleurs, @Environment(\.locale) — accès aux paramètres régionaux.
Le property wrapper @Environment implémente deux mécanismes clés : lire une valeur de l’environnement et s’abonner à ses modifications. Lorsqu’une View est créée, SwiftUI parcourt toutes les propriétés @Environment et les lie aux valeurs correspondantes du contexte actuel. Si une View parent modifie une valeur via le modificateur .environment(), toutes les Views enfants qui lisent cette valeur sont automatiquement redessinées.
Une fonctionnalité importante : @Environment prend en charge les valeurs optionnelles. Si une valeur n’est pas définie dans la hiérarchie, la valeur par défaut définie dans EnvironmentKey est renvoyée. Pour les clés système, la valeur par défaut est toujours raisonnable — par exemple, le schéma de couleurs par défaut est .light. Pour les clés personnalisées, le développeur définit la valeur par défaut dans la méthode defaultValue du protocole EnvironmentKey.
struct EnvironmentReaderView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.locale) var locale
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
VStack {
Text("Current scheme: \(colorScheme == .dark ? "Dark" : "Light")")
Text("Locale: \(locale.identifier)")
Text("Font size: \(sizeCategory)")
}
}
}
Dans l’exemple, la View lit trois valeurs de l’environnement système. Lorsque colorScheme change — par exemple, l’utilisateur a activé le mode sombre dans les réglages — la View se redessine automatiquement avec la nouvelle valeur. De même lorsque la région ou la taille de police (Dynamic Type) change. La View n’a pas besoin de s’abonner aux notifications ni d’appeler refresh — SwiftUI gère cela automatiquement.
SwiftUI fournit des dizaines de valeurs de l’environnement système couvrant divers aspects de l’interface et du comportement. Schéma de couleurs (\.colorScheme) est l’une des valeurs les plus utilisées, permettant d’adapter l’interface aux thèmes clair et foncé. Paramètres régionaux (\.locale) contient les réglages régionaux de l’utilisateur pour le formatage des dates, des nombres et des devises.
Pour Core Data, managedObjectContext (\.managedObjectContext) est utilisé — un contexte transmis via l’environnement depuis le conteneur de persistance. Pour la navigation, dismiss (\.dismiss) est disponible pour fermer l’écran actuel et isPresented (\.isPresented) pour les présentations modales. Pour le calendrier et le fuseau horaire — calendar et timeZone respectivement.
| Key Path | Type | Objectif |
|---|---|---|
| \.colorScheme | ColorScheme | Thème clair ou foncé |
| \.locale | Locale | Paramètres régionaux |
| \.sizeCategory | ContentSizeCategory | Taille de police Dynamic Type |
| \.managedObjectContext | NSManagedObjectContext | Contexte Core Data |
| \.dismiss | DismissAction | Fermer l’écran |
| \.calendar | Calendar | Calendrier actuel |
| \.timeZone | TimeZone | Fuseau horaire |
| \.horizontalSizeClass | UserInterfaceSizeClass | Taille horizontale de l’écran |
Pour accéder aux valeurs système, utilisez le key path avec un point : @Environment(\.dismiss) var dismiss. Le compilateur vérifie l’existence du key path dans EnvironmentValues, donc une clé incorrecte provoquera une erreur de compilation. Apple ajoute de nouvelles valeurs système à chaque version d’iOS — la liste complète est disponible dans la documentation EnvironmentValues.
Malgré des noms similaires, @Environment et @EnvironmentObject ont des objectifs différents. @Environment lit les valeurs système ou personnalisées enregistrées via EnvironmentKey. @EnvironmentObject est un property wrapper pour un ObservableObject transmis par l’environnement par type, sans clé explicite.
@EnvironmentObject est utilisé pour l’injection de dépendances : une View parent crée un objet (par exemple, ViewModel) et le transmet aux Views enfants via le modificateur .environmentObject(). Les Views enfants le reçoivent via @EnvironmentObject et peuvent lire et modifier ses propriétés. @Environment, quant à lui, est en lecture seule pour les valeurs système et ne prend pas en charge le retour d’information.
| Paramètre | @Environment | @EnvironmentObject |
|---|---|---|
| Objectif | Valeurs système et personnalisées | Injection ObservableObject |
| Clé | Key path EnvironmentValues | Par type d’objet |
| Écriture | Lecture seule | Lecture et écriture |
| Valeur personnalisée | Via EnvironmentKey | Via classe ObservableObject |
| Valeur par défaut | Oui (defaultValue) | Non (doit être transmise) |
En pratique : utilisez @Environment pour accéder aux paramètres système (thème, paramètres régionaux, taille de police) et aux configurations personnalisées qui ne changent pas à l’exécution. Utilisez @EnvironmentObject pour transmettre un ViewModel ou un service dans la hiérarchie des Views lorsque l’état doit être modifié à partir de composants enfants.
Examinons la création d’une valeur d’environnement personnalisée. Pour cela, vous devez définir une structure conforme au protocole EnvironmentKey et étendre EnvironmentValues avec une nouvelle propriété. Cela permet de transmettre la configuration du thème ou les paramètres de l’application dans tout l’arbre des Views sans props.
struct AppThemeKey: EnvironmentKey {
static let defaultValue: AppTheme = .system
}
extension EnvironmentValues {
var appTheme: AppTheme {
get { self[AppThemeKey.self] }
set { self[AppThemeKey.self] = newValue }
}
}
enum AppTheme { case system, light, dark }
Le protocole EnvironmentKey nécessite l’implémentation de la propriété statique defaultValue — la valeur qui sera utilisée si la View parent n’a pas défini d’environnement personnalisé. L’extension d’EnvironmentValues ajoute une propriété calculée appTheme utilisant un subscript avec la clé. Après cela, toute View peut lire la valeur via @Environment(\.appTheme).
struct ThemedView: View {
@Environment(\.appTheme) var appTheme
@Environment(\.colorScheme) var colorScheme
var body: some View {
VStack {
if appTheme == .dark || (appTheme == .system && colorScheme == .dark) {
Text("Dark mode active")
.foregroundStyle(.white)
.background(Color.black)
} else {
Text("Light mode active")
.foregroundStyle(.black)
.background(Color.white)
}
}
}
}
struct ContentView: View {
@State private var selectedTheme = AppTheme.system
var body: some View {
ThemedView()
.environment(\.appTheme, selectedTheme)
}
}
ThemedView lit deux environnements : le personnalisé appTheme et le système colorScheme. La combinaison permet une configuration flexible du thème : l’utilisateur peut choisir le thème Clair, Sombre ou Système. Si Système est sélectionné, la valeur est prise de colorScheme, qui change automatiquement lors du basculement du thème dans les réglages iOS. La View parent (ContentView) définit la valeur appTheme via le modificateur .environment().
struct ModalView: View {
@Environment(\.dismiss) var dismiss
@State private var name = ""
var body: some View {
NavigationStack {
Form {
TextField("Your name", text: $name)
Button("Save") { dismiss() }
}
.navigationTitle("Edit Profile")
}
}
}
Cet exemple montre l’utilisation pratique de dismiss — une instance de DismissAction de l’environnement. Appeler dismiss() comme une fonction ferme l’écran modal ou fait revenir le NavigationLink. La seule condition est que la View soit présentée modalement ou se trouve dans un NavigationStack. dismiss est déterminé automatiquement par le contexte : si la View est ouverte comme sheet — le sheet est fermé, si comme popover — le popover est fermé.
Questions fréquentes
Non, @Environment est en lecture seule. Pour modifier des valeurs, utilisez @EnvironmentObject avec ObservableObject ou @Binding. Les EnvironmentKeys personnalisés peuvent avoir un setter dans l’extension, mais une modification via celui-ci ne déclenche pas de mise à jour de l’interface — c’est techniquement possible mais déconseillé.
@Binding crée une connexion bidirectionnelle avec une source de vérité (State, StateObject, ObservableObject). @Environment est une lecture unidirectionnelle depuis le contexte hiérarchique. @Binding convient pour transmettre des données à une View enfant, @Environment — pour accéder aux paramètres système ou globaux.
Définissez une structure implémentant le protocole EnvironmentKey avec un defaultValue statique. Ensuite, étendez EnvironmentValues avec une propriété utilisant getter/setter via subscript[key]. Après l’enregistrement, utilisez @Environment(\.yourKey) pour lire et .environment(\.yourKey, value) pour définir.
SwiftUI fournit plus de 50 valeurs système : colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight et d’autres. Liste complète dans la documentation EnvironmentValues.
Oui, @Environment fonctionne dans Preview, mais les valeurs par défaut peuvent différer du simulateur. Pour tester dans Preview, utilisez le modificateur .environment() directement dans le code Preview : ThemedView().environment(\.colorScheme, .dark). Cela permet de vérifier visuellement différents états de l’environnement.
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