Difference between @environment vs @environmentObject in SwiftUI

Manish Pathak
2 min readMay 2, 2023

Both of them @Environment and @EnvironmentObject are property wrappers while @Environment keeps values with predefined keys, @EnvironmentObject keeps not only predefined keys but also arbitrary values. For example if you need to keep information about your User object which includes name, age, gender etc. you need to use @EnvironmentObject, whereas if you would like to keep whether device is in dark or light mode, system local language, calendar preferences, edit mode it is great for using @Environment.

@Environment is a key/value pair, whereas @EnvironmentObject is just a value identified by its type. Both are variable storage property wrappers.

@Environment(\.locale) var locale: Locale

@EnvironmentObject var user: User // is an object where you keep user-related information

@EnvironmentObject

  • Its similar like @ObservedObject
  • The model should conform to the ObservableObject protocol
  • We need to mark properties in this model as @Published to notify changes to view which actively using the object
  • The model object should be as class for sure
  • No need for default value, because it can read default value from environment. If object is not available in environment, app will crash.
  • Another major difference is, say we have 5 views(V1…V5), if we want to pass a object directly from V1 to V5 we could use @EnvironmentObject rather than @ObservedObject. Set data to be passed in V1 and retrieve it in V5(or wherever needed). Code will be much simple.
  • It will hold only one type of instance at same time environment.
  • Its purely based on views. If a parent view sets environment object all its child can make use of it. If another parent view set another env object, their child’s can make us of it. Eg: If you set environment object in your ContentView in SceneDelegate all its child views can make use of it.

@Environment

  • We can use this to get system-related values like whether apps are running in light or dark mode, core data’s managed object context, size classes, etc…
  • We need to provide proper keys to access its value because it holds the same datatype against multiple keys.

@Environment is value type but @EnvironmentObject is reference type.

You can only use a single instance of objects in @EnvironmentObject.If you add another instance of an object, it will replace the previous one.

But as, @Environment key value pair, just make sure key is different.

You just need to use @EnvironmentObject var object: Object to make an object retrieve the instance from the environment, and inject the instance by .environmentObject(Object())

On the other hand, there are many predefined @Environment system-managed environment values. You can also create custom one. It needs to be struct type and conforms to EnvironmentKey.

Here is an example,

struct SunlightKey: EnvironmentKey {
static var defaultValue: Double = 1.09
}

Then add it to the EnvironmentValues as an extension of it.

Here is a basic example

extension EnvironmentValues {

var sunlight: Double {
get { self[SunlightKey.self] }
set { self[SunlightKey.self] = newValue }
}

}

Then, use it like, @Environment(\.sunlight) var sunlight in view file and inject value by .environment(\.sunlight, 4.05)

Hope, this helps

--

--