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?
CodePudding user response:
$name
is how you access the underlying Publisher
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 a Publisher
that will emit each character of the String
and then complete (It's defined on a Sequence
extension)
If you have:
@MainActor class MyModel:ObservableObject {
@Published private(set) var name = "foo"
....
}
You will see f - o - o
CodePudding user response:
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 returns String.Element
) of the current string, rather than new values of the string when it is swapped out. For that, use $name
. (on which sink
returns a String
type for each change.)