I have the a model with a published name property:
@MainActor class MyModel:ObservableObject {
@Published private(set) var name = ""
....
}
I am wondering why sink works when used on model.$name
and not on model.name.publisher
.
model.$name
.receive(on: RunLoop.main)
.sink { name in
.... <-- it's called. works.
}
.store(in: &subs)
This does not get called:
model.name.publisher
.receive(on: RunLoop.main)
.sink { name in
.... <-- does not get called.
}
.store(in: &subs)
Can someone explain exactly why I have to use the $
sign in front of name and why name.publisher
does not work?
2
Answers
$name
is how you access the underlyingPublisher
of the@Published
property wrapper.This publisher will emit every time the
name
property mutates and probably that’s what you want.With
model.name.publisher
you get aPublisher
that will emit each character of theString
and then complete (It’s defined on aSequence
extension)If you have:
You will see
f - o - o
In this particular case, I understand why it’s confusing.
$name
refers to the publisher within the@Published
property-wrapper. It is what you want.name.publisher
is something within String. Fabio Felici’s answer explains it well. It will cycle through characters (it returnsString.Element
) of the current string, rather than new values of the string when it is swapped out. For that, use$name
. (on whichsink
returns aString
type for each change.)