A dynamic view property that uses a bindable object supplied by an ancestor view to invalidate the current view whenever the bindable object changes.
In practice the main difference between @ObjectBinding and @EnvironmentObject is we don’t need to pass data everywhere. we inject it in at very beginning and then use this keyword to get it on very child view. From above case, we inject it in when we create Container.
Instead of passing data from view A to B and then from B to View C we can pass data directly from A to C using @EnvironmentObject
First, add this as a property of your SceneDelegate
:
var settings = UserSettings()
That creates a settings instance once, and stores it safely. Now go back down to those two lines of code I showed you and change the second line so it passes our settings
property into ContentView
as an environment object, like this:
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(settings))
Once that’s done, the shared UserSettings
instance is available to our content view and any other views it hosts or presents. All you need to do is create a property using the @EnvironmentObject
property wrapper, like this:
@EnvironmentObject var settings: UserSettings
in ContentView.swift
//
// ContentView.swift
// SwiftUI-@EnvironmentObject
//
// Created by Sandesh on 15/04/20.
// Copyright © 2020 Sandesh. All rights reserved.
//
import SwiftUI
class UserSettings: ObservableObject {
@Published var score = 0 // to refresh score value whenenever it updated
}
struct ContentView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
NavigationView {
VStack {
// A button that writes to the environment settings
Button(action: {
self.settings.score += 1
}) {
Text("Increase Score \(self.settings.score)")
}
NavigationLink(destination: firstLevelView()) {
Text("Show Detail View")
}
}
}
}
}
struct firstLevelView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: secondLevelView()) {
Text("Show Detail View")
}
}
}
}
}
struct secondLevelView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
// A text view that reads from the environment settings
NavigationView {
VStack {
// A button that writes to the environment settings
Button(action: {
self.settings.score += 1
}) {
Text("Increase Score \(self.settings.score)")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}