`Republished` property wrapper enabling nested ObservableObjects in SwiftUI
Republished
The @Republished
proprty wrapper allows an ObservableObject
nested
within another ObservableObject
to naturally notify SwiftUI of changes.
It was inspired by @mergesort’s blog post introducing Boutique
.
Problem
Nested ObservableObjects
don’t play well with SwiftUI.
An ObservableObject
is a reference type, not a value type. This means a field on an outer ObservableObject
containing an inner ObservableObject
doesn’t change when the inner object’s one’s changes. As such the outer object will not send the objectWillChange
notification required for SwiftUI to know to rerender views that depend on its data.
Nested ObservableObjects
are often a sign your data model needs some refactoring — but it can also be a nice way to separate code concerns. Boutique
provides a data store as a nestable ObservableObject
. This repo’s Example App uses nested ObservableObjects
to separate its ‘DomainModel’ from its ‘ViewModel’, showcasing a version of the MVVM pattern that separates view-display logic from business logic (and is a bit closer to its original form).
Usage
The outer ObservableObject
should hold the inner one in a var annotated
with the @Republished
property wrapper.
@Republished private var inner: InnerObservableObject
The inner ObservableObject's
objectWillChange
notifications will be
re-emitted by the outer ObservableObject
, allowing it to provide SwiftUI
compatible accessors derived from the inner.
var infoFromInner: String { "\(inner.info)" }
Note: The outer ObservableObject
will only republish notifications
from inner ObservableObjects
that it actually accesses.
SPM
You can use this library via Swift Package Manger by adding a dependency in your Package.swift.
.package(url: "https://github.com/adam-zethraeus/Republished", from: "0.1.0")
Example App
The RepublishedTestApp
contains a simple example of an inner ObservableObject
, used by an outer ObservableObject
view model, to provide data for a regular SwiftUI View
.