2

According to my understanding, if you define a view yourself (as a struct that implements View), then you can declare some var to be an Environment variable, like this:

@Environment(\.isEnabled) var isEnabled

This will give you access to the EnvironmentValues.isEnabled field.

However, it seems like this is only possible within the view definition itself.

Is it possible, given some view v, to get the environment object of that view? or get specific environment values?

hasen
  • 161,647
  • 65
  • 194
  • 231
  • Didn't quite get where do you want to use the Environment Values. The definition of the Environment is "A dynamic view property that reads a value from the view’s environment.". I believe it must be inside the View because it is dynamic and depends on how the View is rendered. By binding them with @Environment(\.KeyPath) we can use them as regular variables. Do you want to store a specific value and pass it around? – Victor Sanchez Dec 05 '19 at 12:57
  • @VictorSanchez for background on this, see my other question: https://stackoverflow.com/questions/59169436 – hasen Dec 05 '19 at 13:35

1 Answers1

2

I assume that taking into account that SwiftUI is reactive state managed framework then yes, directly you cannot ask for internal view environment value, actually because you can't be sure when that environment is set up for this specific view. However you can ask that view to tell you about its internal state, when view is definitely knowns about it... via binding.

An example code (a weird a bit, but just for demo) how this can be done see below.

struct SampleView: View {
    @Environment(\.isEnabled) private var isEnabled

    var myState: Binding<Bool>?

    var body: some View {
        VStack {
            Button(action: {}) { Text("I'm \(isEnabled ? "Enabled" : "Disabled")") }
            report()
        }
    }

    func report() -> some View {
        DispatchQueue.main.async {
            self.myState?.wrappedValue = self.isEnabled
        }
        return EmptyView()
    }
}

struct TestEnvironmentVar: View {

    @State private var isDisabled = false
    @State private var sampleState = true

    var body: some View {
        VStack {
            Button(action: {
                self.isDisabled.toggle()
            }) {
                Text("Toggle")
            }
            Divider()
            sampleView()
                .disabled(isDisabled)
        }
    }

    private func sampleView() -> some View {
        VStack {
            SampleView(myState: $sampleState)
            Text("Sample is \(sampleState ? "Enabled" : "Disabled")")
        }
    }
}


struct TestEnvironmentVar_Previews: PreviewProvider {
    static var previews: some View {
        TestEnvironmentVar()
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690