Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Environment vs @EnvironmentObject

Tags:

swiftui

What's the difference between @Environment and @EnvironmentObject in SwiftUI?

From what I found from the documents, @Environment seems to be meant to be used for global dependencies like ColorScheme. But I couldn't find any precise difference between them. For example, can they be used interchangeably?

like image 441
Hamoonist Avatar asked Sep 23 '19 11:09

Hamoonist


4 Answers

Here is the notes I have prepared for myself. Could be useful,

@EnvironmentObject

  • Its similar like @ObservedObject
  • The model should confirm 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 is 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 same datatype against multiple keys.

Thanks!👨🏻‍💻

like image 160
Karthick Selvaraj Avatar answered Jan 04 '23 11:01

Karthick Selvaraj


I want to add something to others' answer.

@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

like image 30
Shahriar Nasim Nafi Avatar answered Jan 04 '23 12:01

Shahriar Nasim Nafi


@Enviroment gives you access to values of properties such as user settings (e.g colour scheme, layout direction etc.) or properties of the view such as EditMode or PresentationMode. @EnviromentObject is defined by you and available to all views and changes to it drive updates to your views.

like image 25
LuLuGaGa Avatar answered Jan 04 '23 12:01

LuLuGaGa


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(\.locale) var locale: Locale

@EnvironmentObject var user: User // is an object where you keep user-related information
like image 26
atalayasa Avatar answered Jan 04 '23 12:01

atalayasa