Wesley de Groot's Blog
@Environment variables

Back

@Environment variables

SwiftUI provides a way to pass data down the view hierarchy using @Environment variables. These variables are environment-dependent and can be accessed from any child view. They are useful for sharing common data or settings across the app, such as color schemes, locale, or accessibility settings.

When you create an @Environment variable, SwiftUI automatically manages its value for you. This means that when the environment changes, the view will automatically update to reflect the new value.

Creating an @Environment Variable

To create an @Environment variable, you can use one of the built-in environment keys provided by SwiftUI, such as .colorScheme, .locale, or .accessibilityEnabled. For example, to access the color scheme environment variable, you can use the following code:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text("Hello, World!")
            .foregroundColor(colorScheme == .dark ? .white : .black)
    }
}

In this example, the colorScheme variable is an @Environment variable that holds the current color scheme of the app. The text color is set based on the color scheme (dark or light) using a ternary operator.

Custom @Environment Variables

You can also create custom @Environment variables to pass custom data or settings down the view hierarchy. To define a custom @Environment variable, you need to create a new type that conforms to the EnvironmentKey protocol and extend EnvironmentValues to introduce the value.

Here's an example of how you can define a custom @Environment variable:

private struct MyCustomKey: EnvironmentKey {
    // Create a default value for the custom environment key
    static let defaultValue: String = "Default Value"
}

extension EnvironmentValues {
    /// Define a custom environment variable
    var myCustomValue: String {
        get { self[MyCustomKey.self] }
        set { self[MyCustomKey.self] = newValue }
    }
}

In this example, we define a custom key MyCustomKey that holds a default string value. We then extend EnvironmentValues to introduce the custom value myCustomValue using the key.

You can now use the custom @Environment variable in your views like this:

/// Pass custom environment value
struct ContentView: View {
    var body: some View {
        VStack {
            SecondView()
                .environment(\.myCustomValue, "hello there")
        }
    }
}

/// Access custom environment value
struct SecondView: View {
    @Environment(\.myCustomValue) var customValue

    var body: some View {
        Text(customValue)
    }
}

In this example, the customValue variable is an @Environment variable that holds the custom value defined earlier. The text view displays the value of the custom environment variable.

iOS 18 and later (easier)

/// Setup environment key
extension EnvironmentValues {
    @Entry var myCustomValue: String = "Default Value"
}

/// Pass custom environment value
struct ContentView: View {
    var body: some View {
        VStack {
            SecondView()
                .environment(\.myCustomValue, "hello there")
        }
    }
}

/// Access custom environment value
struct SecondView: View {
    @Environment(\.myCustomValue) var customValue

    var body: some View {
        Text(customValue)
    }
}

Caveats

When using @Environment variables, keep in mind that they are not meant for sharing complex data structures or models across the view hierarchy. For more complex data sharing, consider using @EnvironmentObject or other data sharing techniques.

Wrap up

@Environment variables are a powerful tool in SwiftUI for sharing common data or settings across the app. By creating custom @Environment variables, you can extend this functionality to suit your app's specific needs. Just remember to use them judiciously and follow best practices to avoid potential pitfalls.

Resources:

x-twitter mastodon github linkedin discord threads instagram whatsapp bluesky square-rss sitemap