A linked View property that reads a `ObservableObject` supplied by an ancestor view that will automatically invalidate its view when the object changes.
State Management
Share Data between Views using @EnvironmentObject
class User: ObservableObject {
@Published var name = "Enes Karaosman"
}
// View 1
struct EditView: View {
@EnvironmentObject var user: User
var body: some View {
TextField("Name", text: $user.name)
}
}
// View 2
struct DisplayView: View {
@EnvironmentObject var user: User
var body: some View {
Text(user.name)
}
}
// Container View to demonstrate communication
struct DemoView: View {
let user = User()
var body: some View {
VStack {
EditView()//.environmentObject(user)
DisplayView()//.environmentObject(user)
}
// Since both views wrapped by same container
// We can bind here as well.
.environmentObject(user)
}
}
EnvironmentObject does not require to be passed explicitly down to child views.
// Lets demonstrate the information above
// Dummy class for testing EnvironmentObject
class EnvTest: ObservableObject {
@Published var testStr = "inital"
}
// In SceneDelegate, add those
let envTest = EnvTest()
let contentView = ContentView() // Assume ContentView is initial View
.environmentObject(envTest)
struct ContentView: View {
// Now we are able to read environmentObject
// passed from SceneDelegate, could be anywhere
@EnvironmentObject() var envTest: EnvTest
var body: some View {
VStack(spacing: 16) {
Text("Main")
TextField("Placeholder", text: $envTest.testStr)
.textFieldStyle(RoundedBorderTextFieldStyle())
Rectangle().foregroundColor(.red).frame(height: 2)
Child1() // Dummy Child View
}.padding()
}
}
Lets also create 2 dummy child view.
struct Child1: View {
@EnvironmentObject var envTest: EnvTest
var body: some View {
VStack {
Text("Child 1").font(.headline)
Text(envTest.testStr)
Rectangle().foregroundColor(.blue).frame(height: 2)
Child2()
}
}
}
struct Child2: View {
@EnvironmentObject() var envTest: EnvTest
var body: some View {
VStack {
Text("Child 2").font(.headline)
TextField("Placeholder", text: $envTest.testStr)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
Now when we edit envTest (EnvironmentObject) in any child, the changes reflected everywhere it is used.