How to tell SwiftUI views to bind to nested ObservableObjects
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
SwiftUI redraws a view when the object that view is observing publishes objectWillChange. That works well until one observable object owns another observable object. At that point, many developers expect nested changes to "bubble up" automatically, but ObservableObject does not do that for you.
Why Nested ObservableObject State Is Tricky
Consider this model structure:
At first glance, it looks reasonable. AppState is observable, and settings is marked @Published. The catch is that @Published only emits when the settings property itself changes to a different object. Mutating settings.username does not replace the settings reference, so the parent object does not publish a new change automatically.
That is why a view observing AppState can miss updates originating inside UserSettings.
Best Pattern: Observe the Child Directly
If a subview cares about child state, pass the child object into that subview and let the subview observe it directly.
This is the most idiomatic solution because the view observes the object that actually owns the changing property.
Forward Child Changes When the Parent Must React
Sometimes the parent view model must expose derived state or coordinate multiple nested models. In that case, forward the child's publisher into the parent's objectWillChange.
Now any view observing AppState will refresh when settings changes internally. This is the right approach when the parent genuinely represents a composed model rather than just a container of unrelated references.
Value Types Are Often Simpler
If the nested state is small and does not need its own subscriptions or object identity, a value type is usually cleaner than a nested observable class.
Because settings is a struct, mutating username mutates the settings value itself, which triggers the @Published publisher on the parent.
Property Wrapper Ownership Still Matters
Nested observables often look broken when the real bug is ownership:
- Use
@StateObjectwhen a view creates and owns the observable object. - Use
@ObservedObjectwhen the object is created elsewhere and injected. - Use
@EnvironmentObjectwhen shared state should be read across many branches.
If the parent creates AppState, it should usually own it with @StateObject. If a child view receives UserSettings from the parent, the child should use @ObservedObject.
Avoid Giant Root Models
A common architecture smell is forcing every view to depend on a giant root AppState object. That makes refresh behavior harder to predict because everything depends on everything else.
A better rule is: each view should observe the smallest object that contains the state it actually needs. This keeps redraw behavior more obvious and reduces accidental coupling.
It also makes previews and tests simpler:
The subview can be previewed independently without constructing the whole application state tree.
Common Pitfalls
One common mistake is marking the child reference @Published and assuming that inner child mutations will trigger the parent automatically. They will not unless the reference itself changes.
Another issue is forgetting to retain the Combine subscription when forwarding objectWillChange. If the cancellable is not stored, the forwarding stops immediately.
Developers also sometimes use nested observable classes where a plain struct would be easier and less error-prone. Object identity is useful, but it adds complexity that small state objects often do not need.
Finally, avoid observing the parent everywhere just because it is available. If a view needs child state, observing the child directly is usually the clearest design.
Summary
- Nested
ObservableObjectchanges do not automatically propagate to a parent observer. - The cleanest fix is usually to observe the child object directly in the subview that uses it.
- If the parent must react to child updates, forward the child's
objectWillChange. - Small nested state is often better modeled as a value type inside a
@Publishedproperty. - Correct
@StateObjectand@ObservedObjectownership is essential for predictable SwiftUI updates.
Related reading
- How to test equality of Swift enums with associated values
- How to test widget that is instantiated in didUpdateWidget in Flutter?
- How to throttle search based on typing speed in iOS UISearchBar?
- How to toggle a UITextField secure text entry hide password in Swift?
- How to train a tensorflow network using JNI on Android?
- How to transfer some data to another Fragment?
- How to trap on UIViewAlertForUnsatisfiableConstraints?
- How to turn on front flash light programmatically in Android?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.