on
SwiftUI - @Published
The @Published
attribute is a property wrapper that allows access to a Publisher
type using either the $
syntax or the projectedValue
struct property.
@propertyWrapper public struct Published<Value> {
/// Initialize the storage of the Published property as well as
/// the corresponding `Publisher`.
public init(initialValue: Value)
{…}
/// The property that can be accessed with the `$` syntax and
/// allows access to the `Publisher`
public var projectedValue: Published<Value>.Publisher { mutating
get }
}
A class using a @Published
attribute must conform to the ObservableObject
protocol — part of the Combine framework — which synthesizes an objectWillChange
publisher that emits the changed value before any of its @Published
properties changes .
Under the hood, the objectWillChange
publisher will receive a new input whenever one of a @Published
property is about to be mutated.
@Published
works well with SwiftUI — coupled with a MVVM architecture — as one can make a view model conform the ObservableObject
and mark its underlying properties as @Published
so that views always reflect the latest model changes.
Creating a ViewModel
class conforming to the ObservableObject
enables us to work with a @Published
property and process its underlying publisher.
class ViewModel: ObservableObject {
@Published var keyword = ""
func processKeyword() {
self.$keyword // or self._keyword.projectedValue
.debounce(for: 0.5, scheduler: DispatchQueue.main)
.sink { self.sortArticles(byKeyword: $0) }
.store(in: &cancellable)
}
}
The sink
method creates a subscriber and immediately receive values from the upstream publisher enabling us to sort the articles by keyword.
Notice how the $
syntax or projectedValue
property from @Published
is similar to the @State
ones however both provide with different types — respectively a Publisher
type and a Binding
type — .
Because SwiftUI and Combine are tightly related, views observing these @Published
properties will actually react to any new values emitted by their underlying publishers through the objectWillChange
synthetizer.
— Conclusion
The @Published
attribute is a great means of communication between the UI and its related data as one can observe a model object and reflect the UI with its latest changes.
It works well with the MVVM architecture as it enables us to observe the underlying stored properties through a publisher.
When conforming to the ObservableObject
protocol, the system automatically synthesizes an objectWillChange
publisher which will listen to the @Published properties mutations and send the information back to a view.