What is the purpose of @EnvironmentObject when we have @Binding property wrapper ? I am having trouble figuring out why @EnvironmentObject is needed. I took a look at these posting but its not quite what I am looking for EnvironmentObject in SwiftUI How to use BindableObjects (EnviromentObject)?
I also looked at their documentation which was too thin. https://developer.apple.com/documentation/swiftui/environmentobject
I'll try to explain generally. We have the next modifiers @State
, @StateObject
, @ObservedObject
@Published
, @EnvironmentObject
, and @Binding
.
@State
- declares local value property. Apple recommends using them as less as possible because the @State
property should be used only inside the view and be responsible for small UI things. It should have a simple value type, not a reference type, otherwise, it won't update the UI for you.@StateObject
- declares and instantiates object instance. Usually, it is your data model that should be displayed. The object must conform to the ObservableObject protocol.@ObservedObject
- declares a property that uses an instance marked as a @StateObject
that has been passed from the parent view. It is a good choice when you do not want your reusable view to be dependent on the external objects. This way you passing the @StateObject
directly to each child view.@EnvironmentObject
- also declares a property as a @ObservedObject
does, but this modifier should be used when you pass an instance to all subviews tree. To pass the instance to the child view just call YourViewToPresent().environmentObject(<your object>)
. And then this child view and its children can access an instance using @EnvironmentObject var instance: YourInstance
without additional effort or passings. This modifier finds an instance of the declared type, so you cannot declare more than one object of the same type in the same environment. You also should be careful and do not use it too much since this may open a lot of architectural backdoors on your project(library, framework).@Published
- should be used to mark ObservableObject
variable to re-render the view when it's changed.@Binding
- defines that the property can modify real Source of Truth(@State, @ObservedObject, @EnvironmentObject
). When you are passing one of the properties from 1-3 points to the view you have to declare the property in child view as @Binding
to create a reference. Use $
sign to pass the Source of Truth to the child: MessageDetails(message: $message)
. By changing the @Binding
you will be changing actual Source of Truth.
For more info recommend to watch Data Flow Through SwiftUIBonus:
@Environment
- is used to get environment values by using keyPath @Environment(\.colorScheme)
. You can read this value, but you cannot set this value. If the value is changed it causes UI re-render. Some values may be updated updated by SwiftUI. To find all available keys look for documentation of the EnvironmentValues
. You also can override as well as add custom EnvironmentValue
.