SwiftUI finds two similar methods for passing environment variables: Environment

(_ keyPath:, _ value:) and environmentObject

(_ object:).

Go to the official account [iOS Development Stack] to learn more SwiftUI, iOS development related content.

The first thing to be clear about is that both methods are used to set environment variables, which affect the view of the set variable and all its children, and the passing process does not need to be specified.

That is, suppose you have three views, view1, view2, and view3, where view2 and view3 are subviews of view1, and if you want to use the environment variables set by view1 in view2 and view3, You only need to use @environmentobject or @environment directly in the view without explicitly passing arguments when creating view2 and view3.

@EnvironmentObject

Use @environmentobject to illustrate the above statement:

// Public id -- iOS development stack
class OfficalAccount: ObservableObject {
    @Published var amount = 3000 // Number of subscribers
}

struct DetailView: View {
    @EnvironmentObject var account: OfficalAccount

    var body: some View {
        VStack {
            Button("Increase Score in detailView") {
                account.amount + = 1
            }

            Text("account: \(account.amount)")}}}struct DetailView2: View {
    @EnvironmentObject var account: OfficalAccount

    var body: some View {
        Text("Score: \(account.amount)")}}struct ContentView: View {
    @StateObject var account = OfficalAccount(a)var body: some View {
        VStack {
            Button("Increase Score") {
                account.amount + = 1
            }
            
            DetailView(a)DetailView2()
        }
        .environmentObject(account)
    }
}
Copy the code

The above example is based on the number of subscribers to my public account (” iOS development stack “). You can see that ContentView creates DetailView and DetailView2 without passing the variable Accout directly, but the result is that the quantity display in these two subviews increases with the button click.

There are a few points to note about using environmentObject above for environment variable delivery:

  • use@Environment,@StateObject,@ObservedObjectThe wrapped classes must be complied withObservableObjectProtocols, and only classes, not structures, {% label danger@Non-class type ‘OfficalAccount’ cannot conform to class protocol ‘ObservableObject’ %}
  • @PublishedAlso can only beclass{% label danger@’wrappedValue’ is unavailable: @Published is only available on properties of classes %}
  • use@EnvironmentObjectThe wrapped variable does not need to be initialized; the compiler gets the value of the object from the environment variable
  • The value of an environment variable can be changed in a subview, and the change is passed through the current view hierarchy

@Environment

In the case of @Environment, it is mainly used to handle current system Settings such as language, time zone, dark mode, CoreData Context, etc.

One big difference is that @environment (_ keyPath:) requires a keyPath parameter of type keyPath, which in most cases is already defined in EnvironmentValues. Such as managedObjectContext/locale, etc.

The following uses CoreData as an example to illustrate how to use it:

// App.swift
.
let persistenceController = PersistenceController.shared
.
var body: some Scene {
    WindowGroup {
        ContentView()
            .environment(\.managedObjectContext, persistenceController.container.viewContext)
    }
}
.

// ContentView.swift
.
@Environment(\.managedObjectContext) private var viewContext
.
let newItem = Item(context: viewContext)
newItem.platform = 1
.
Copy the code

In this example, we create the persistenceController in app. swift and pass the value to the ContentView by calling.environment. ContentView uses @Environment(\.ManagedobJectContext) private var viewContext to retrieve this Environment variable.

Aside from requiring a KeyPath and dealing primarily with the system’s built-in Environment variables mentioned above, @Environment and @environmentobject are not much different in usage.

Go to the official account [iOS Development Stack] to learn more SwiftUI, iOS development related content.

conclusion

By using environment variables flexibly, you can make the development process simpler and write less code about passing values (forward and reverse) between pages. By comparing Environment and EnvironmentObject, we have learned more about the use of Environment variables in SwiftUI.