@Environment Object | SwiftUI

Jul 7, 2021 2 min read
@Environment Object | SwiftUI

What is @Environment Object

SwiftUI’s @EnvironmentObject property wrapper lets us create views that rely on shared data, often across an entire SwiftUI app. For example, if you create a user that will be shared across many parts of your app, you should use @EnvironmentObject.

By using @EnvironmentObject we’re saying that value will be provided by the SwiftUI environment rather than explicitly created by the view. If one view changes the object all other views automatically get updated

If you are unsure which property wrapper to choose in any situation, checkout the link below:
Which SwiftUI property wrapper to choose in any situation
Decide which property wrapper is the right choice for your needs.

Warning: When a view using @EnvironmentObject is shown, SwiftUI will immediately search the environment for an object of the correct type. If such an object can’t be found – i.e., if you forgot to place it in the environment – then your app will immediately crash. When you use @EnvironmentObject you are effectively promising that object will exist in the environment by the time it is needed, a bit like using implicitly unwrapped optionals.

Screenshot

@EnvironmentObject Example:

struct ContentView: View {
    
    var prospects = Prospects()
    
    var body: some View {
        TabView {
            ProspectsView(filter: .none)
                .tabItem {
                    Image(systemName: "person.3")
                    Text("Everyone")
                }
            ProspectsView(filter: .contacted)
                .tabItem {
                    Image(systemName: "checkmark.circle")
                    Text("Contacted")
                }
            ProspectsView(filter: .uncontacted)
                .tabItem {
                    Image(systemName: "questionmark.diamond")
                    Text("Uncontacted")
                }
        }
        .environmentObject(prospects)
    }
}

struct ProspectsView: View {

    enum FilterType {
        case none, contacted, uncontacted
    }
    
    @EnvironmentObject var prospects: Prospects
    
    let filter: FilterType
    
    var title: String {
        switch filter {
        case .none:
            return "Everyone"
        case .contacted:
            return "Contacted people"
        case .uncontacted:
            return "Uncontacted people"
        }
    }
    
    var body: some View {
        NavigationView {
            Text("People: \(prospects.people.count)")
                .navigationBarTitle(title)
                .navigationBarItems(trailing: Button(action: {
                    let prospect = Prospect()
                    prospect.name = "Paul Hudson"
                    prospect.emailAddress = "[email protected]"
                    self.prospects.people.append(prospect)
                }) {
                    Image(systemName: "qrcode.viewfinder")
                    Text("Scan")
                })
        }
    }
}


class Prospect: Identifiable, Codable {
    var id = UUID()
    var name = "Anonymous"
    var emailAddress = ""
    var isContacted = false
}

class Prospects: ObservableObject {
    @Published var people: [Prospect]
    
    init() {
        self.people = []
    }
}

Reference

Great! Next, complete checkout for full access to ArturoFM.
Welcome back! You've successfully signed in.
You've successfully subscribed to ArturoFM.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.