2

I'm attempting to crawl out of the proverbial Neophyte abyss here.

I'm beginning to grasp the use of @EnvironmentObject till I notice the .environmentObject() view operator in the docs.

Here's my code:

import SwiftUI

struct SecondarySwiftUI: View {
    @EnvironmentObject var settings: Settings

    var body: some View {
        ZStack {
            Color.red
            Text("Chosen One: \(settings.pickerSelection.name)")
        }.environmentObject(settings) //...doesn't appear to be of use.
    }

    func doSomething() {}
}

I tried to replace the use of the @EnvironmentObject with the .environmentObject() operator on the view.
I got a compile error for missing 'settings' def.

However, the code runs okay without the .environmentObject operator.

So my question, why have the .environmentObject operator?

Does the .environmentObject() instantiates an environmentObject versus the @environmentObject accesses the instantiated object?

Frederick C. Lee
  • 9,019
  • 17
  • 64
  • 105

1 Answers1

5

Here is demo code to show variants of EnvironmentObject & .environmentObject usage (with comments inline):

struct RootView_Previews: PreviewProvider {
    static var previews: some View {
        RootView().environmentObject(Settings()) // environment object injection
    }
}

class Settings: ObservableObject {
    @Published var foo = "Foo"
}

struct RootView: View {
    @EnvironmentObject var settings: Settings // declaration for request of environment object

    @State private var showingSheet = false
    var body: some View {
        VStack {
            View1() // environment object injected implicitly as it is subview
            .sheet(isPresented: $showingSheet) {
                View2() // sheet is different view hierarchy, so explicit injection below is a must
                    .environmentObject(self.settings) // !! comment this out and see run-time exception
            }
            Divider()
            Button("Show View2") {
                self.showingSheet.toggle()
            }
        }
    }
}

struct View1: View {
    @EnvironmentObject var settings: Settings // declaration for request of environment object
    var body: some View {
        Text("View1: \(settings.foo)")
    }
}

struct View2: View {
    @EnvironmentObject var settings: Settings // declaration for request of environment object
    var body: some View {
        Text("View2: \(settings.foo)")
    }
}

So, in your code ZStack does not declare needs of environment object, so no use of .environmentObject modifier.

Asperi
  • 228,894
  • 20
  • 464
  • 690
  • 1
    I got the runtime error: Thread 1: Fatal error: No ObservableObject of type Settings found. A View.environmentObject(_:) for Settings may be missing as an ancestor of this view. ---this was flagged with Struct View1. – Frederick C. Lee Jan 19 '21 at 22:25