EnvironmentObject

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.

Last updated