Differences between @State, @Binding, @ObservedObject, and @EnvironmentObject

Tests SwiftUI state ownership and propagation. @State owns local value types; @Binding borrows for two-way edits; @ObservedObject accepts an external ObservableObject; @EnvironmentObject reads one from the environment.
WHAT THIS TESTS: This question probes your mental model of SwiftUI's declarative data flow and ownership. Interviewers want to see that you know which wrapper owns the data, which merely borrows it, and how reference-type state differs from value-type state across a view tree.
A GOOD ANSWER COVERS: A good answer hits four things in order. First, @State is for local value-type state owned by the view itself; SwiftUI stores it outside the struct and mutates it in place, and it should be private. Second, @Binding is for two-way access to state owned by an ancestor; it does not own the data, it only reads and writes it, making it ideal for custom controls and sheet dismissal. Third, @ObservedObject is for reference-type objects that conform to ObservableObject; the view holds a reference but does not own or create the object, and the parent typically passes it down. Fourth, @EnvironmentObject is for shared ObservableObject instances that are injected higher in the view hierarchy with environmentObject and retrieved implicitly by any descendant that declares the need; this avoids excessive prop drilling. You should also mention that only @State and @Binding work well with value types like structs and enums, while @ObservedObject and @EnvironmentObject require classes.
COMMON WRONG ANSWERS: Red flags include saying @State can hold a class, confusing @ObservedObject with a globally shared object, or claiming @EnvironmentObject creates the object automatically. Another mistake is omitting that @Binding is two-way; some candidates describe it as read-only. Also, watch for candidates who say @State is stored inside the view struct; SwiftUI actually stores it in external storage and reinitializes the struct on every update.
LIKELY FOLLOW-UPS: Interviewers often push deeper by asking when to use @StateObject instead of @ObservedObject, how the environment differs from dependency injection, or what happens if an environment object is missing at runtime. They may also ask about performance implications of ObservableObject publishing, or how to avoid unnecessary view redraws using objectWillChange or @Published granularity.
ONE CONCRETE EXAMPLE: Imagine a toggle in a settings row. The parent view owns a Boolean using @State. It passes a @Binding into the row subview so the row can flip the toggle. The row itself does not own the truth. Meanwhile, a network service class conforming to ObservableObject is created in the root view and passed into a list as an @ObservedObject. Finally, a user session object is placed into the environment at the app root with environmentObject, and a deep profile view reads it via @EnvironmentObject without the intermediate views knowing it exists.
Read the original → developer.apple.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.