@Environment în SwiftUI — property wrapper pentru citirea valorilor din mediul sistemului, distribuite automat în ierarhia View. Componentul oferă acces la schema de culori, locale, dimensiunea fontului, managedObjectContext și zeci de alți parametri de sistem. Conform Apple Developer Documentation (2025), @Environment garantează că orice modificare a valorii mediului determină redesenarea tuturor View-urilor abonate, asigurând actualizarea reactivă a interfeței fără apeluri manuale.
Puncte cheie
@Environment — este un property wrapper SwiftUI destinat citirii valorilor din mediul sistemului. Mediul este un container ierarhic de valori pe care SwiftUI le distribuie automat de la View-urile părinte la cele copil. Fiecare valoare de mediu este identificată printr-o cheie — un tip conform protocolului EnvironmentKey.
Mecanismul mediului amintește de dependency injection la nivel de framework: sistemul oferă un set predefinit de valori — schema de culori (light/dark), locale, dimensiunea fontului, managedObjectContext pentru Core Data, dismiss pentru închiderea ecranului și multe altele. Un View care a declarat @Environment cu o cheie specifică primește automat valoarea curentă și se redesenează la modificarea acesteia.
Arhitectura mediului SwiftUI se bazează pe protocolul EnvironmentValues — o structură care conține toate valorile de sistem. Fiecare valoare este stocată ca o proprietate a acestei structuri cu getter și setter. @Environment folosește key path pentru a accesa o proprietate specifică: @Environment(\.colorScheme) — acces la schema de culori, @Environment(\.locale) — la locale.
Property wrapper @Environment implementează două mecanisme cheie: citirea valorii din mediu și abonarea la modificările acestuia. La crearea View-ului, SwiftUI parcurge toate proprietățile @Environment și le leagă de valorile corespunzătoare din contextul curent. Dacă un View părinte modifică valoarea prin modifierul .environment(), toate View-urile copil care citesc această valoare se redesenează automat.
O caracteristică importantă: @Environment suportă valori opționale. Dacă valoarea nu este setată în ierarhie, se returnează valoarea implicită definită în EnvironmentKey. Pentru cheile de sistem, valoarea implicită este întotdeauna rezonabilă — de exemplu, schema de culori implicită .light. Pentru chei personalizate, programatorul însuși definește valoarea implicită în metoda defaultValue a protocolului EnvironmentKey.
struct EnvironmentReaderView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.locale) var locale
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
VStack {
Text("Schema curentă: \(colorScheme == .dark ? "Dark" : "Light")")
Text("Locale: \(locale.identifier)")
Text("Dimensiune font: \(sizeCategory)")
}
}
}
În exemplu, View citește trei valori de sistem ale mediului. La modificarea colorScheme — de exemplu, utilizatorul a activat tema întunecată în setări — View se redesenează automat cu noua valoare. Similar la schimbarea regiunii sau a dimensiunii fontului (Dynamic Type). View nu trebuie să se aboneze la notificări sau să apeleze reîmprospătarea — SwiftUI gestionează acest lucru automat.
SwiftUI oferă zeci de valori de sistem ale mediului, acoperind diverse aspecte ale interfeței și comportamentului. Schema de culori (\.colorScheme) — una dintre cele mai solicitate valori, permițând adaptarea interfeței la tema deschisă și întunecată. Locale (\.locale) conține setările regionale ale utilizatorului pentru formatarea datelor, numerelor și valutei.
Pentru Core Data se folosește managedObjectContext (\.managedObjectContext) — contextul transmis prin mediu din persistence container. Pentru navigare sunt disponibile dismiss (\.dismiss) pentru închiderea ecranului curent și isPresented (\.isPresented) pentru vizualizări modale. Pentru calendar și fus orar — respectiv calendar și timeZone.
| Key Path | Tip | Destinație |
|---|---|---|
| \.colorScheme | ColorScheme | Temă deschisă sau întunecată |
| \.locale | Locale | Setări regionale |
| \.sizeCategory | ContentSizeCategory | Dimensiunea fontului Dynamic Type |
| \.managedObjectContext | NSManagedObjectContext | Context Core Data |
| \.dismiss | DismissAction | Închiderea ecranului |
| \.calendar | Calendar | Calendarul curent |
| \.timeZone | TimeZone | Fus orar |
| \.horizontalSizeClass | UserInterfaceSizeClass | Dimensiunea orizontală a ecranului |
Pentru a accesa valorile de sistem, utilizați key path prin punct: @Environment(\.dismiss) var dismiss. Compilatorul verifică existența key path-ului în EnvironmentValues, deci o cheie greșită va cauza o eroare în faza de compilare. Noi valori de sistem sunt adăugate de Apple cu fiecare versiune iOS — lista actuală este disponibilă în documentația EnvironmentValues.
În ciuda numelor similare, @Environment și @EnvironmentObject rezolvă sarcini diferite. @Environment citește valori de sistem sau personalizate înregistrate prin EnvironmentKey. @EnvironmentObject — este un property wrapper pentru ObservableObject, transmis prin mediu după tip, fără o cheie explicită.
@EnvironmentObject este utilizat pentru dependency injection: un View părinte creează un obiect (de exemplu, ViewModel) și îl transmite View-urilor copil prin modifierul .environmentObject(). View-urile copil îl primesc prin @EnvironmentObject și pot atât citi, cât și modifica proprietățile sale. @Environment, în schimb — doar pentru citire a valorilor de sistem și nu suportă feedback.
| Parametru | @Environment | @EnvironmentObject |
|---|---|---|
| Destinație | Valori de sistem și personalizate | Injecție ObservableObject |
| Cheie | Key path EnvironmentValues | După tipul obiectului |
| Scriere | Doar citire | Citire și scriere |
| Valoare personalizată | Prin EnvironmentKey | Prin clasa ObservableObject |
| Valoare implicită | Există (defaultValue) | Nu (trebuie transmisă) |
În practică: utilizați @Environment pentru acces la parametrii de sistem (temă, locale, dimensiunea fontului) și configurații personalizate care nu se modifică în runtime. Utilizați @EnvironmentObject pentru transmiterea ViewModel sau serviciului prin ierarhia View, când este necesară modificarea stării din componentele copil.
Să analizăm crearea unei valori personalizate de mediu. Pentru aceasta, trebuie să definiți o structură conformă cu protocolul EnvironmentKey și să extindeți EnvironmentValues cu o nouă proprietate. Aceasta permite transmiterea configurației temei sau setărilor aplicației prin întregul arbore View fără 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 }
Protocolul EnvironmentKey necesită implementarea proprietății statice defaultValue — valoarea care va fi utilizată dacă View-ul părinte nu a setat un mediu personalizat. Extinderea EnvironmentValues adaugă proprietatea calculată appTheme, folosind subscript cu cheia. După aceasta, orice View poate citi valoarea prin @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("Mod întunecat activ")
.foregroundStyle(.white)
.background(Color.black)
} else {
Text("Mod luminos activ")
.foregroundStyle(.black)
.background(Color.white)
}
}
}
}
struct ContentView: View {
@State private var selectedTheme = AppTheme.system
var body: some View {
ThemedView()
.environment(\.appTheme, selectedTheme)
}
}
ThemedView citește două medii: appTheme personalizat și colorScheme de sistem. Combinația permite implementarea unei configurări flexibile a temei: utilizatorul poate alege tema „Deschisă”, „Întunecată” sau „Sistem”. Dacă este selectată cea de sistem — valoarea este preluată din colorScheme, care se modifică automat la schimbarea temei în setările iOS. View-ul părinte (ContentView) setează valoarea appTheme prin modifierul .environment().
struct ModalView: View {
@Environment(\.dismiss) var dismiss
@State private var name = ""
var body: some View {
NavigationStack {
Form {
TextField("Your name", text: $name)
Button("Salvare") { dismiss() }
}
.navigationTitle("Edit Profile")
}
}
}
Acest exemplu demonstrează utilizarea practică a dismiss — o instanță DismissAction din mediu. Apelul dismiss() ca funcție închide ecranul modal sau returnează NavigationLink. Singura cerință — View-ul trebuie să fie prezentat modal sau să se afle în interiorul NavigationStack. dismiss se determină automat din context: dacă View-ul este deschis ca sheet — se închide sheet, dacă ca popover — se închide popover.
Întrebări frecvente
Nu, @Environment este destinat doar pentru citire. Pentru modificarea valorilor utilizați @EnvironmentObject cu ObservableObject sau @Binding. EnvironmentKey-urile personalizate pot avea setter în extensie, dar modificarea prin acesta nu declanșează actualizarea UI — este posibil tehnic, dar nu este recomandat.
@Binding creează o conexiune bidirecțională cu sursa de adevăr (State, StateObject, ObservableObject). @Environment — citire unidirecțională din contextul ierarhic. @Binding este potrivit pentru transmiterea datelor către un View copil, @Environment — pentru accesul la setările de sistem sau globale.
Definiți o structură care implementează protocolul EnvironmentKey cu static defaultValue. Apoi extindeți EnvironmentValues cu o proprietate cu getter/setter prin subscript[key]. După înregistrare, utilizați @Environment(\.yourKey) pentru citire și .environment(\.yourKey, value) pentru setare.
SwiftUI oferă peste 50 de valori de sistem: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight și altele. Lista completă în documentația EnvironmentValues.
Da, @Environment funcționează în Preview, dar valorile implicite pot diferi de simulator. Pentru testare în Preview, utilizați modifierul .environment() direct în codul Preview: ThemedView().environment(\.colorScheme, .dark). Aceasta permite verificarea vizuală a diferitelor stări ale mediului.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și