I found myself coming back to this post so felt I'd add some extra insight in to the difference between @Published
and CurrentValueSubject
.
One main difference can be found in the documentation for @Published
:
When the property changes, publishing occurs in the property’s willSet block, meaning subscribers receive the new value before it’s actually set on the property.
Additionally, conversation on the Swift Forums note that @Published
is intended for use with SwiftUI.
With regards to @Published
publishing in the willSet
block of it's property, consider the following example:
class PublishedModel {
@Published var number: Int = 0
}
let pModel = PublishedModel()
pModel.$number.sink { number in
print("Closure: \(number)")
print("Object: \(pModel.number) [read via closure]")
}
pModel.number = 1
print("Object: \(pModel.number) [read after assignment]")
This produces the following output:
Closure: 0
Object: 0 [read via closure]
Closure: 1
Object: 0 [read via closure]
Object: 1 [read after assignment]
Contrast this with another example where we keep everything the same, except replacing @Published
with CurrentValueSubject
:
class CurrentValueSubjectModel {
var number: CurrentValueSubject<Int, Never> = .init(0)
}
let cvsModel = CurrentValueSubjectModel()
cvsModel.number.sink { number in
print("Closure: \(number)")
print("Object: \(cvsModel.number.value) [read via closure]")
}
cvsModel.number.send(1)
print("Object: \(cvsModel.number.value) [read after assignment]")
Output:
Closure: 0
Object: 0 [read via closure]
Closure: 1
Object: 1 [read via closure] // <— Here is the difference
Object: 1 [read after assignment]
After updating number
to 1, reading the object's CurrentValueSubject
's value property within the closure prints the new value instead of the old value as with @Published
.
In summary, use @Published
within your ObservableObjects
for your SwiftUI views. If you're looking to create some sort of model object with an instance property that holds a current value and also publishes it's changes after they are set, use CurrentValueSubject
.