In SwiftUI, @Environment is used to propagate values and information down the view hierarchy without having to explicitly pass them as parameters. In this tutorial, we'll take an overview of @Environment Property Wrapper and learn how we can define our custom environment value using EnvironmentKey and EnvironmentValues.

1. What is Environment Property Wrapper?

@Environment is a property wrapper in SwiftUI that allows a view to access values stored in the environment. The environment is a container for values that are global to the current view hierarchy, such as the device's appearance mode (light/dark), locale, and more. You can use @Environment to access these values without directly passing them as parameters to your views. For example:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme
    
    var body: some View {
        Text("Color Scheme: \(colorScheme)")
    }
}

2. What is EnvironmentKey?

EnvironmentKey is a protocol that you can adopt to define your own custom environment values. So, it is a key for accessing values in the environment.

3. What is EnvironmentValues?

EnvironmentValues is a type that holds the actual values of the environment. So, it is a collection of environment values propagated through a view hierarchy. SwiftUI provides a set of predefined environment values that you can access using the @Environment property wrapper like colorScheme, locale etc.

4. How to create SwiftUI Custom Environment Values?

4.1 Defining the Custom Environment Key

First, you need to create a custom environment key by creating a new type that conforms to the EnvironmentKey protocol. Now add the a defaultValue for environment key.

struct MyCustomEnvironmentKey: EnvironmentKey {
    static var defaultValue: String = "Default Value"
}

4.2 Extend EnvironmentValues

Next, you need to extend the EnvironmentValues, which holds the actual value of the environment.

extension EnvironmentValues {
    var myCustomValue: String {
        get { self[MyCustomEnvironmentKey.self] }
        set { self[MyCustomEnvironmentKey.self] = newValue }
    }
}
  • This myCustomValue computed property provides a way to get and set the value associated with MyCustomEnvironmentKey in the environment.
  • Using self[MyCustomEnvironmentKey.self], SwiftUI looks up the environment to find the value associated with the custom key.

4.3 Using the Custom Environment Value in a View

Now, you can use the new custom environment value in your SwiftUI view. For example:

struct ContentView: View {
    @Environment(\.myCustomValue) var myCustomValue
    
    var body: some View {
        Text("Custom Value: \(myCustomValue)")
    }
}

4.4 Set or Update Environment Value

To set or update the environment value, you need to use .environment modifier. For example to modify myCustomValue form App file:

struct SampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.myCustomValue, "Hello, World!!")
        }
    }
}

You can use this .environment modifier from any SwiftUI View.

This was a simple example myCustomValue was String type. But you can create a custom Environment Value with other available types in Swift. The combination of @Environment, EnvironmentValues, and EnvironmentKey allows SwiftUI to efficiently manage and propagate values that are relevant to the entire view hierarchy, making it easy to build responsive and dynamic user interfaces.