How to use @Environment to share data between views in SwiftUI

Desilio Neto
3 min readFeb 13, 2024

--

If you need to have access to data in different views SwiftUI provides the property wrapper @Environment for this propose. To use it first you need to create a class that is observable. I create a very simple one with just one field:

import Foundation
import SwiftUI

@Observable
class BackgroundColor {
var value: Color = .red
}

I will use it to share this value set the background of 2 views. Next step is go to the entry screen of your app, this file is located usually on the top of you project and the name is “name of your project”App in my case the file is named SharingDataWithEnvironmentSwiftUIApp. After open the file I added one instance of the class that I created before and also added the modifier .environment to the ContentView() and passed the object created.

import SwiftUI

@main
struct SharingDataWithEnvironmentSwiftUIApp: App {
@State private var label = BackgroundColor()

var body: some Scene {
WindowGroup {
ContentView()
.environment(label)
}
}
}

Now is time to use our the Environment in our views. I created 2 simple views one with a Text and a Button, this button call the Second Screen that have also a Text and a button that changes the value of the Environment object to green. Boot views receives the background color from the Environment variable. Pay attention that before use it you should setup the preview first, otherwise it will crash, so let’s do it. To setup the preview is easy, you just need to use the environment modifier and pass a instance of the observable class that we created before, in our case BackgroundColor():

#Preview {
ContentView()
.environment(BackgroundColor())
}

You should do it with every view that you will use the Environment property. Last step is call the Environment property on our views, so you can use it. We just declare an @Environment passing the type we created as reference BackgroundColor.self. I named the variable as backgroundColor but you can use any name your want.

@Environment(BackgroundColor.self) private var backgroundColor

This is the complete code of the ContentView:

import SwiftUI

struct ContentView: View {
@Environment(BackgroundColor.self) private var backgroundColor

var body: some View {
NavigationStack {
VStack {
Text("Background color from environment")

NavigationLink("Go to second screen") {
SecondView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(backgroundColor.value)
}
}
}

#Preview {
ContentView()
.environment(BackgroundColor())
}

As you can see I am setting the background color using the variable that I declared before. And finally the code of the SecondView:

import SwiftUI

struct SecondView: View {
@Environment(BackgroundColor.self) private var backgroundColor

var body: some View {
VStack {
Text("Background color from environment")

Button("change color to green ") {
backgroundColor.value = .green
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(backgroundColor.value)
}
}

#Preview {
SecondView()
.environment(BackgroundColor())
}

In this view if you press the button you will update the value of the Environment object and it will update the background color of this view and also of our ContentView. In our example you use just 2 view but if you have a lots of views it would updated all of them at the same time, this is useful when you is working with app settings for example. This is the result:

That’s all for today if you enjoy give me a clap and follow to be updated about the next tutorials, the code of this tutorial can be found on my GitHub, if you have any question please let me know on the comments. Until next time, happy coding!

--

--