@Environment ve SwiftUI — property wrapper pro čtení hodnot ze systémového prostředí, automaticky šířených v hierarchii View. Komponenta poskytuje přístup k barevnému schématu, locale, velikosti písma, managedObjectContext a desítkám dalších systémových parametrů. Podle Apple Developer Documentation (2025), @Environment garantuje, že jakákoli změna hodnoty prostředí způsobí překreslení všech přihlášených View, zajišťuje reaktivní aktualizaci rozhraní bez ručních volání.
Hlavní body
@Environment — je SwiftUI property wrapper určený pro čtení hodnot ze systémového prostředí. Prostředí je hierarchický kontejner hodnot, který SwiftUI automaticky šíří od rodičovských View k podřízeným. Každá hodnota prostředí je identifikována klíčem — typem odpovídajícím protokolu EnvironmentKey.
Mechanismus prostředí připomíná dependency injection na úrovni frameworku: systém poskytuje předdefinovanou sadu hodnot — barevné schéma (světlé/tmavé), locale, velikost písma, managedObjectContext pro Core Data, dismiss pro zavření obrazovky a mnoho dalších. View, které deklarovalo @Environment s určitým klíčem, automaticky obdrží aktuální hodnotu a při její změně se překreslí.
Architektura prostředí SwiftUI je založena na protokolu EnvironmentValues — struktuře obsahující všechny systémové hodnoty. Každá hodnota je uložena jako vlastnost této struktury s getterem a setterem. @Environment používá key path pro přístup ke konkrétní vlastnosti: @Environment(\.colorScheme) — přístup k barevnému schématu, @Environment(\.locale) — k locale.
Property wrapper @Environment implementuje dva klíčové mechanismy: čtení hodnoty z prostředí a přihlášení k jejím změnám. Při vytváření View SwiftUI prochází všechny vlastnosti @Environment a propojuje je s odpovídajícími hodnotami z aktuálního kontextu. Pokud rodičovské View změní hodnotu pomocí modifikátoru .environment(), všechna podřízená View, která tuto hodnotu čtou, se automaticky překreslí.
Důležitá vlastnost: @Environment podporuje volitelné hodnoty. Pokud hodnota není v hierarchii nastavena, vrátí se výchozí hodnota definovaná v EnvironmentKey. U systémových klíčů je výchozí hodnota vždy rozumná — například výchozí barevné schéma .light. Pro vlastní klíče vývojář sám určuje výchozí hodnotu v metodě defaultValue protokolu EnvironmentKey.
struct EnvironmentReaderView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.locale) var locale
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
VStack {
Text("Aktuální schéma: \(colorScheme == .dark ? "Dark" : "Light")")
Text("Locale: \(locale.identifier)")
Text("Velikost písma: \(sizeCategory)")
}
}
}
V příkladu View čte tři systémové hodnoty prostředí. Při změně colorScheme — například uživatel zapnul tmavý režim v nastavení — se View automaticky překreslí s novou hodnotou. Podobně při změně regionu nebo velikosti písma (Dynamic Type). View nemusí odebírat oznámení ani volat obnovení — SwiftUI to spravuje automaticky.
SwiftUI poskytuje desítky systémových hodnot prostředí, pokrývající různé aspekty rozhraní a chování. Barevné schéma (\.colorScheme) — jedna z nejžádanějších hodnot, umožňující přizpůsobit rozhraní světlému a tmavému motivu. Locale (\.locale) obsahuje regionální nastavení uživatele pro formátování dat, čísel a měn.
Pro Core Data se používá managedObjectContext (\.managedObjectContext) — kontext předávaný prostředím z persistence containeru. Pro navigaci jsou k dispozici dismiss (\.dismiss) pro zavření aktuální obrazovky a isPresented (\.isPresented) pro modální zobrazení. Pro kalendář a časové pásmo — calendar a timeZone.
| Key Path | Typ | Účel |
|---|---|---|
| \.colorScheme | ColorScheme | Světlý nebo tmavý motiv |
| \.locale | Locale | Regionální nastavení |
| \.sizeCategory | ContentSizeCategory | Velikost písma Dynamic Type |
| \.managedObjectContext | NSManagedObjectContext | Kontext Core Data |
| \.dismiss | DismissAction | Zavření obrazovky |
| \.calendar | Calendar | Aktuální kalendář |
| \.timeZone | TimeZone | Časové pásmo |
| \.horizontalSizeClass | UserInterfaceSizeClass | Horizontální velikost obrazovky |
Pro přístup k systémovým hodnotám použijte key path přes tečku: @Environment(\.dismiss) var dismiss. Kompilátor kontroluje existenci key path v EnvironmentValues, takže chybný klíč způsobí chybu při kompilaci. Nové systémové hodnoty přidává Apple s každou verzí iOS — aktuální seznam je k dispozici v dokumentaci EnvironmentValues.
Navzdory podobným názvům, @Environment a @EnvironmentObject řeší různé úkoly. @Environment čte systémové nebo vlastní hodnoty registrované přes EnvironmentKey. @EnvironmentObject — je property wrapper pro ObservableObject, předávaný prostředím podle typu, bez explicitního klíče.
@EnvironmentObject se používá pro dependency injection: rodičovské View vytvoří objekt (například ViewModel) a předá jej podřízeným View pomocí modifikátoru .environmentObject(). Podřízené View jej obdrží přes @EnvironmentObject a mohou jak číst, tak měnit jeho vlastnosti. @Environment je — pouze pro čtení systémových hodnot a nepodporuje zpětnou vazbu.
| Parametr | @Environment | @EnvironmentObject |
|---|---|---|
| Účel | Systémové a vlastní hodnoty | Injekce ObservableObject |
| Klíč | Key path EnvironmentValues | Podle typu objektu |
| Zápis | Pouze čtení | Čtení a zápis |
| Vlastní hodnota | Přes EnvironmentKey | Přes třídu ObservableObject |
| Výchozí hodnota | Ano (defaultValue) | Ne (nutno předat) |
V praxi: používejte @Environment pro přístup k systémovým parametrům (motiv, locale, velikost písma) a vlastním konfiguracím, které se nemění za běhu. Používejte @EnvironmentObject pro předávání ViewModel nebo služby hierarchií View, když je třeba měnit stav z podřízených komponent.
Podívejme se na vytvoření vlastní hodnoty prostředí. K tomu je třeba definovat strukturu odpovídající protokolu EnvironmentKey a rozšířit EnvironmentValues o novou vlastnost. To umožňuje předávat konfiguraci motivu nebo nastavení aplikace přes celý strom View bez 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 }
Protokol EnvironmentKey vyžaduje implementaci statické vlastnosti defaultValue — hodnoty, která se použije, pokud rodičovské View nenastavilo vlastní prostředí. Rozšíření EnvironmentValues přidává vypočítávanou vlastnost appTheme pomocí subscript s klíčem. Poté může jakékoli View číst hodnotu přes @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("Tmavý režim aktivní")
.foregroundStyle(.white)
.background(Color.black)
} else {
Text("Světlý režim aktivní")
.foregroundStyle(.black)
.background(Color.white)
}
}
}
}
struct ContentView: View {
@State private var selectedTheme = AppTheme.system
var body: some View {
ThemedView()
.environment(\.appTheme, selectedTheme)
}
}
ThemedView čte dvě prostředí: vlastní appTheme a systémové colorScheme. Kombinace umožňuje implementovat flexibilní nastavení motivu: uživatel si může vybrat „Světlý”, „Tmavý” nebo „Systémový” motiv. Pokud je vybrán systémový — hodnota se bere z colorScheme, které se automaticky mění při přepnutí motivu v nastavení iOS. Rodičovské View (ContentView) nastavuje hodnotu appTheme pomocí modifikátoru .environment().
struct ModalView: View {
@Environment(\.dismiss) var dismiss
@State private var name = ""
var body: some View {
NavigationStack {
Form {
TextField("Your name", text: $name)
Button("Uložit") { dismiss() }
}
.navigationTitle("Edit Profile")
}
}
}
Tento příklad demonstruje praktické použití dismiss — instance DismissAction z prostředí. Volání dismiss() jako funkce zavře modální obrazovku nebo vrátí NavigationLink. Jediným požadavkem je, že View musí být zobrazeno modálně nebo být uvnitř NavigationStack. dismiss se automaticky určuje z kontextu: pokud je View otevřeno jako sheet — zavře se sheet, pokud jako popover — zavře se popover.
Často kladené otázky
Ne, @Environment je určen pouze pro čtení. Pro změnu hodnot používejte @EnvironmentObject s ObservableObject nebo @Binding. Vlastní EnvironmentKey mohou mít setter v rozšíření, ale změna přes něj nevyvolá aktualizaci UI — je to technicky možné, ale nedoporučuje se.
@Binding vytváří obousměrné propojení se zdrojem pravdy (State, StateObject, ObservableObject). @Environment — jednosměrné čtení z hierarchického kontextu. @Binding je vhodný pro předávání dat podřízenému View, @Environment — pro přístup k systémovým nebo globálním nastavením.
Definujte strukturu implementující protokol EnvironmentKey se static defaultValue. Poté rozšiřte EnvironmentValues o vlastnost s getterem/setterem přes subscript[key]. Po registraci používejte @Environment(\.yourKey) pro čtení a .environment(\.yourKey, value) pro nastavení.
SwiftUI poskytuje více než 50 systémových hodnot: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight a další. Úplný seznam v dokumentaci EnvironmentValues.
Ano, @Environment funguje v Preview, ale výchozí hodnoty se mohou lišit od simulátoru. Pro testování v Preview použijte modifikátor .environment() přímo v kódu Preview: ThemedView().environment(\.colorScheme, .dark). To umožňuje vizuálně kontrolovat různé stavy prostředí.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také