Environment property wrapper is used to read values from a view’s (well 😜)environment. We can use this property wrapper to read a value stored in view’s environment by using an EnvironmentValues key path during property declaration.
For example, we can create property to read current color scheme:
@Environment(\.colorScheme) var colorScheme: ColorScheme
and use this to show dark/light content on the screen:
if colorScheme == .dark {
DarkContent()
} else {
LightContent()
}
The benefit of using this property wrapper is that when this environment value changes, SwiftUI updates parts of your view that depend on the value.
The environment property wrapper is not limited to just those provided by SwiftUI, but you can create your own environment variables as well.
Today, we will use this to access colors created as color assets in your Assets folder.
Let’s start by creating colors, we will create three colors that will have both dark and light(any appearance) as shown in the screenshot below
If you are looking for same colors, here are the hex values:
blue: dark(#75D5FF), any appearance(#0096FF)
orange: dark(#FFD478), any appearance(#FF9300)
purple: dark(#D783FF), any appearance(#9437FF)
Once we have our colors ready, let’s create a constants struct to access these values so we don’t have to type Color(“colorName”) everywhere.
struct Constants {
static var blue = Color("blue")
static var orange = Color("orange")
static var purple = Color("purple")
}
Next we will create environment key for each color by conforming to EnvironmentKey protocol, which requires a defaultValue variable to be defined as shown below:
struct BlueColorKey: EnvironmentKey {
static var defaultValue: Color = Constants.blue
}struct OrangeColorKey: EnvironmentKey {
static var defaultValue: Color = Constants.orange
}struct PurpleColorKey: EnvironmentKey {
static var defaultValue: Color = Constants.purple
}
Note that we are setting default value for each key to the corresponding color.
Once we have our keys defined, we will move on to creating environment values for these keys by adding computed properties to the EnvironmentValues struct.
extension EnvironmentValues {
var blueColor: Color {
get { self[BlueColorKey.self] }
set { self[BlueColorKey.self] = newValue }
}
var orangeColor: Color {
get { self[OrangeColorKey.self] }
set { self[OrangeColorKey.self] = newValue }
}
var purpleColor: Color {
get { self[PurpleColorKey.self] }
set { self[PurpleColorKey.self] = newValue }
}
}
Note: getter and setter for each property can be accessed via its type. For example, to get blue color key, we will use self[BlueColorKey.self] and to set we will add new value into self[BlueColorKey.self]
Now, it’s time to use these environment values.
We will create a few variables. Let’s start with environment variables:
struct EnvironmentVairableExample: View {
@Environment(\.blueColor) var blueColor
@Environment(\.orangeColor) var orangeColor
@Environment(\.purpleColor) var purpleColor
}
We also want to see colors in dark and light mode so let’s create variable for color scheme and a timer publisher (to change theme every 5 seconds):
struct EnvironmentVairableExample: View {
@Environment(\.blueColor) var blueColor
@Environment(\.orangeColor) var orangeColor
@Environment(\.purpleColor) var purpleColor
@State private var colorScheme = ColorScheme.dark
let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
}
Let’s add view body to show some content:
struct EnvironmentVairableExample: View {
@Environment(\.blueColor) var blueColor
@Environment(\.orangeColor) var orangeColor
@Environment(\.purpleColor) var purpleColor
@State private var colorScheme = ColorScheme.dark
let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
HStack {
Image(systemName: "heart.fill")
.foregroundColor(purpleColor)
Text("DevTechie")
.foregroundColor(blueColor)
Image(systemName: "heart.fill")
.foregroundColor(purpleColor)
}
.font(.largeTitle)
Text("Learn by example!")
.font(.headline)
.foregroundColor(orangeColor)
}
.preferredColorScheme(colorScheme)
.onReceive(timer) { _ in
colorScheme = colorScheme == .dark ? .light : .dark
}
}
}
And we get this: 👇
With that we have reached the end of this article. Thank you once again for reading. Subscribe to our weekly newsletter at https://www.devtechie.com