23 - Creating & Accessing Environment Values in SwiftUI

Managing the state of your user interface is a crucial part of any SwiftUI application. In SwiftUI, environment values are one of the mechanisms provided to handle shared state across multiple views. Environment values can be accessed or set from anywhere in the view hierarchy and are particularly useful for sharing common data or functionality.

Consider an example in which you create a custom environment value to dynamically change the theme of your app:

// Defining a custom environment value
struct ThemeKey: EnvironmentKey {
  static let defaultValue: Theme = .light
}

extension EnvironmentValues {
  var theme: Theme {
    get { self[ThemeKey.self] }
    set { self[ThemeKey.self] = newValue }
  }
}

// Enum for the different themes
enum Theme {
  case light, dark
}

extension View {
  func theme(_ theme: Theme) -> some View {
    environment(\.theme, theme)
  }
}

struct ThemedView: View {
  @Environment(\.theme) var theme: Theme

  var body: some View {
    VStack {
      if theme == .light {
        Text("Light Theme")
          .foregroundColor(.black)
          .background(Color.white)
      } else {
        Text("Dark Theme")
          .foregroundColor(.white)
          .background(.black)
      }
    }
    .padding()
  }
}

struct ContentView: View {
  @State var theme: Theme = .light

  var body: some View {
    VStack {
      Button("Switch Theme") {
        // Setting our custom environment value
        switch theme {
        case .dark:
          theme = .light
        case .light:
          theme = .dark
        }
      }
      ThemedView()
    }
    .theme(theme)
  }
}

Your preview should look like this:

You can create a custom environment value to share state across views.

In the above code:

By using environment values, you can efficiently share common state and behavior between views, simplifying your code and making your views more reusable.