…but it can be a pain because WritableKeyPath is a misnomer. (There still aren't set-only properties. ) What do people do when they want to use the method to set an optional with a non-optional?
However, I need to set properties of the Published object, and Publishers.MapKeyPath doesn't work with that overload, so I think I'm stuck with sink. And if that's the case, map isn't necessary, because you can assign a non-optional to an optional, with =, in the sink closure.
I'm not sure the KeyPath can work for properties in this case, as the path is to the publisher, not the property. The regular assign (with the appropriate optional overload) may work.
…but how can we avoid having to store the AnyCancellable manually? That's what I love about this new assign overload, but I don't know how it was implemented. Would it have even been possible to implement without private API?
Ah, right. The method isn't designed for that. It's to assign a new value to an @Published property, not to mutate a property of an @Published property. (unless that property itself is an @Published property).
class PublishedObject {
@Published var a: Int? = 3
}
class Test: ObservableObject {
@Published var container = PublishedObject()
let subject = CurrentValueSubject<Int, Never>(4)
func test() {
subject
.map({ $0 })
.assign(to: container.$a)
}
}
let object = Test()
object.container.$a.sink(receiveValue: { value in
print(value) // Optional(3), Optional(4)
})
object.test()
Note that container doesn't have to be @Published. The only requirement here is that the target property is @Published.
The assign(to:) method connects its subscription lifecycle to that of the target publisher somehow. I don't think you need private APIs for that and it might be possible to build something yourself where you connect the subscription lifecycle to the lifecycle of the target property somehow.