@Environment i SwiftUI — property wrapper för att läsa värden från systemmiljön, som automatiskt sprids i View-hierarkin. Komponenten ger åtkomst till färgschema, locale, teckenstorlek, managedObjectContext och dussintals andra systemparametrar. Enligt Apple Developer Documentation (2025) garanterar @Environment att varje ändring av ett miljövärde orsakar omritning av alla prenumererade vyer, vilket säkerställer reaktiv uppdatering av gränssnittet utan manuella anrop.
Huvudpunkter
@Environment — är en SwiftUI property wrapper avsedd för att läsa värden från systemmiljön. Miljön är en hierarkisk behållare av värden som SwiftUI automatiskt sprider från föräldravisningar till underordnade visningar. Varje miljövärde identifieras av en nyckel — en typ som överensstämmer med EnvironmentKey-protokollet.
Miljömekanismen påminner om dependency injection på ramverksnivå: systemet tillhandahåller en fördefinierad uppsättning värden — färgschema (ljust/mörkt), locale, teckenstorlek, managedObjectContext för Core Data, dismiss för att stänga skärmen och många andra. En vy som deklarerat @Environment med en specifik nyckel tar automatiskt emot det aktuella värdet och ritas om när det ändras.
Arkitekturen för SwiftUI-miljön är baserad på EnvironmentValues-protokollet — en struktur som innehåller alla systemvärden. Varje värde lagras som en egenskap i denna struktur med getter och setter. @Environment använder key path för att komma åt en specifik egenskap: @Environment(\.colorScheme) — åtkomst till färgschema, @Environment(\.locale) — till locale.
Property wrappern @Environment implementerar två nyckelmekanismer: läsning av värdet från miljön och prenumeration på dess ändringar. När en vy skapas går SwiftUI igenom alla @Environment-egenskaper och binder dem till motsvarande värden från den aktuella kontexten. Om en föräldraview ändrar värdet via .environment()-modifieraren, kommer alla underordnade vyer som läser detta värde automatiskt att ritas om.
En viktig egenskap: @Environment stöder valfria värden. Om ett värde inte är inställt i hierarkin returneras standardvärdet definierat i EnvironmentKey. För systemnycklar är standardvärdet alltid rimligt — till exempel standardfärgschemat .light. För anpassade nycklar bestämmer utvecklaren själv standardvärdet i defaultValue-metoden i EnvironmentKey-protokollet.
struct EnvironmentReaderView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.locale) var locale
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
VStack {
Text("Aktuellt schema: \(colorScheme == .dark ? "Dark" : "Light")")
Text("Locale: \(locale.identifier)")
Text("Teckenstorlek: \(sizeCategory)")
}
}
}
I exemplet läser en vy tre systemmiljövärden. När colorScheme ändras — till exempel användaren har aktiverat mörkt läge i inställningarna — ritas vyn automatiskt om med det nya värdet. Likaså vid ändring av region eller teckenstorlek (Dynamic Type). Vyn behöver inte prenumerera på notifikationer eller anropa uppdatering — SwiftUI hanterar detta automatiskt.
SwiftUI tillhandahåller dussintals systemmiljövärden som täcker olika aspekter av gränssnitt och beteende. Färgschema (\.colorScheme) — ett av de mest efterfrågade värdena, som gör det möjligt att anpassa gränssnittet till ljust och mörkt tema. Locale (\.locale) innehåller användarens regionala inställningar för formatering av datum, siffror och valutor.
För Core Data används managedObjectContext (\.managedObjectContext) — kontexten som överförs via miljön från persistence-behållaren. För navigering finns dismiss (\.dismiss) för att stänga den aktuella skärmen och isPresented (\.isPresented) för modala vyer. För kalender och tidszon — calendar respektive timeZone.
| Key Path | Typ | Syfte |
|---|---|---|
| \.colorScheme | ColorScheme | Ljust eller mörkt tema |
| \.locale | Locale | Regionala inställningar |
| \.sizeCategory | ContentSizeCategory | Dynamic Type teckenstorlek |
| \.managedObjectContext | NSManagedObjectContext | Core Data-kontext |
| \.dismiss | DismissAction | Stänga skärm |
| \.calendar | Calendar | Aktuell kalender |
| \.timeZone | TimeZone | Tidszon |
| \.horizontalSizeClass | UserInterfaceSizeClass | Horisontell skärmstorlek |
För att komma åt systemvärden, använd key path med punkt: @Environment(\.dismiss) var dismiss. Kompilatorn kontrollerar att key path finns i EnvironmentValues, så en felaktig nyckel orsakar ett kompileringsfel. Nya systemvärden läggs till av Apple med varje iOS-version — aktuell lista finns i EnvironmentValues-dokumentationen.
Trots liknande namn löser @Environment och @EnvironmentObject olika uppgifter. @Environment läser system- eller anpassade värden registrerade via EnvironmentKey. @EnvironmentObject — är en property wrapper för ObservableObject, som överförs via miljön efter typ, utan explicit nyckel.
@EnvironmentObject används för dependency injection: en föräldraview skapar ett objekt (till exempel ViewModel) och skickar det till underordnade vyer via .environmentObject()-modifieraren. Underordnade vyer tar emot det via @EnvironmentObject och kan både läsa och ändra dess egenskaper. @Environment är däremot — endast läsning av systemvärden och stöder inte återkoppling.
| Parameter | @Environment | @EnvironmentObject |
|---|---|---|
| Syfte | System- och anpassade värden | ObservableObject-injektion |
| Nyckel | Key path EnvironmentValues | Efter objekttyp |
| Skrivning | Endast läsning | Läsning och skrivning |
| Anpassat värde | Via EnvironmentKey | Via ObservableObject-klass |
| Standardvärde | Finns (defaultValue) | Finns inte (måste skickas) |
I praktiken: använd @Environment för åtkomst till systemparametrar (tema, locale, teckenstorlek) och anpassade konfigurationer som inte ändras under körning. Använd @EnvironmentObject för att överföra ViewModel eller tjänst via View-hierarkin när tillstånd måste ändras från underordnade komponenter.
Låt oss titta på att skapa ett anpassat miljövärde. För detta måste du definiera en struktur som överensstämmer med EnvironmentKey-protokollet och utöka EnvironmentValues med en ny egenskap. Detta gör det möjligt att överföra temakonfiguration eller appinställningar genom hela vyträdet utan 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 }
EnvironmentKey-protokollet kräver implementering av den statiska egenskapen defaultValue — värdet som kommer att användas om föräldravisningen inte har ställt in en anpassad miljö. EnvironmentValues-utökningen lägger till den beräknade egenskapen appTheme, med subscript med nyckeln. Efter detta kan vilken vy som helst läsa värdet 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("Mörkt läge aktivt")
.foregroundStyle(.white)
.background(Color.black)
} else {
Text("Ljust läge aktivt")
.foregroundStyle(.black)
.background(Color.white)
}
}
}
}
struct ContentView: View {
@State private var selectedTheme = AppTheme.system
var body: some View {
ThemedView()
.environment(\.appTheme, selectedTheme)
}
}
ThemedView läser två miljöer: anpassad appTheme och system colorScheme. Kombinationen gör det möjligt att implementera flexibel temainställning: användaren kan välja tema ”Ljust”, ”Mörkt” eller ”System”. Om system är valt — hämtas värdet från colorScheme, som automatiskt ändras när temat växlas i iOS-inställningarna. Föräldravisningen (ContentView) ställer in appTheme-värdet via .environment()-modifieraren.
struct ModalView: View {
@Environment(\.dismiss) var dismiss
@State private var name = ""
var body: some View {
NavigationStack {
Form {
TextField("Your name", text: $name)
Button("Spara") { dismiss() }
}
.navigationTitle("Edit Profile")
}
}
}
Detta exempel demonstrerar praktisk användning av dismiss — en DismissAction-instans från miljön. Anrop av dismiss() som en funktion stänger den modala skärmen eller returnerar en NavigationLink. Det enda kravet är att vyn måste presenteras modalt eller finnas inuti NavigationStack. dismiss bestäms automatiskt från kontexten: om vyn är öppnad som sheet — stängs sheet, om som popover — stängs popover.
Vanliga frågor
Nej, @Environment är endast avsedd för läsning. För att ändra värden, använd @EnvironmentObject med ObservableObject eller @Binding. Anpassade EnvironmentKey kan ha en setter i en utökning, men ändring via den utlöser inte UI-uppdatering — detta är tekniskt möjligt men rekommenderas inte.
@Binding skapar en tvåvägsförbindelse med sanningskällan (State, StateObject, ObservableObject). @Environment — enkelriktad läsning från den hierarkiska kontexten. @Binding är lämplig för att överföra data till en underordnad vy, @Environment — för åtkomst till system- eller globala inställningar.
Definiera en struktur som implementerar EnvironmentKey-protokollet med static defaultValue. Utöka sedan EnvironmentValues med en egenskap med getter/setter via subscript[key]. Efter registrering, använd @Environment(\.yourKey) för läsning och .environment(\.yourKey, value) för inställning.
SwiftUI tillhandahåller över 50 systemvärden: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight och andra. Fullständig lista i EnvironmentValues-dokumentationen.
Ja, @Environment fungerar i Preview, men standardvärden kan skilja sig från simulatorn. För testning i Preview, använd .environment()-modifieraren direkt i Preview-koden: ThemedView().environment(\.colorScheme, .dark). Detta gör det möjligt att visuellt kontrollera olika miljötillstånd.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också