@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:
Read more
- A Guide to UI Testing in Swift • 15 minutes reading time.
- Easy Publishers • 2 minutes reading time.
- Simplifying multiplatform Colors • 15 minutes reading time.
Share
Share Mastodon Twitter LinkedIn Facebook