Code Monkey home page Code Monkey logo

swift-environmentobject-demo's Introduction

SwiftUI @EnvironmentObject Demo

According to the SwiftUI documentation, @EnvironmentObject is a dynamic view property that uses a bindable object supplied by an ancestor view to invalidate the current view whenever the bindable object changes (source).

Essentially, you can use it to manage access to global state. [Hacking with Swift has a great article that explains the differences between @State, @ObservableObject, and @EnvironmentObject.

Particularly, it says There’s a third type of property available to use, which is @EnvironmentObject. This is a value that is made available to your views through the application itself – it’s shared data that every view can read if they want to.

It turns out, however, that while values put into the environment nicely percolate down the view hierarchy, this is not the case for modals.

Let's assume the following code:

class AppState: ObservableObject {
  @Published var counter = 0
}

struct ContentView: View {
  @EnvironmentObject var state: AppState
  @State var presentDetailsView = false
  @State var presentDetailsViewNoEnvironment = false
  
  var body: some View {
    NavigationView {
      VStack {
        Button(action: { self.state.counter += 1 }) {
          Text("Current value: \(state.counter)")
        }

        // 1

        Button(action: { self.presentDetailsView = true }) {
          Text("Present details")
        }
        Button(action: { self.presentDetailsViewNoEnvironment = true }) {
          Text("Present details w/o Environment (will crash)")
        }
      }
      .navigationBarTitle("@EnvironmentObject: Master")
      // 2
    }
  }
}

struct DetailsView: View {
  @EnvironmentObject var state: AppState
  
  var body: some View {
    Text("The value is \(state.counter)")
  }
}

If you now insert the following code at location (1), you will see that you can navigate from the master view to the details view as expected, and the details view can access the counter state via the global environment:

        NavigationLink(destination: DetailsView()) {
          Text("Navigate to details")
        }

However, adding the following code at location (2) will result in a crash:

      .sheet(isPresented: $presentDetailsViewNoEnvironment) {
        DetailsView()
      }
Fatal error: No observable object of type AppState.Type found.
A View.environmentObject(_:) for AppState.Type may be missing as an ancestor of this view.: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-21.1.2/Core/EnvironmentObject.swift, line 171

Instead, in order to present the details view as a modal, you have to pass the state on, like so:

      .sheet(isPresented: $presentDetailsView) {
        DetailsView().environmentObject(self.state)
      }

Looking at the view hierarchy in the view debugger, we can see that thethis actually makes sense, as a modal screen is added to the view hierarchy in parallel to the original ContentView.

When navigating from ContentView to DetailsView using a NavigationLink, DetailsView becomes a child of ContentView:

View hierarchy when using NavigationLink

When displaying a modal sheet using sheet(isPresented:content:), however, DetailsView will not become a child of ContentView. Instead, the hosting view will be instantiated in parallel to the originating view.

View hierarchy when using sheet(isPresented:content:)

swift-environmentobject-demo's People

Contributors

peterfriese avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.