I ran into this too. I tried a few different ways that didn't work. Using combine to observe the values didn't work, but I did some digging and found something that might be viable, although it's a little convoluted.
So @Observable
is not just making something conform to ObservableObject,
it's its own thing, it's writing some of your code for you. So if you expand the macro (right click on @Observable)
it will expand the code it's augmenting your code with. You'll see a bunch of @ObservationTracked macros revealed for your properties. There's some other stuff too, but not specific to your property.
@ObservationTracked
var test: String = ""
...
@ObservationIgnored private var _test: String
If you expand that macro you now see the getter and setter for your property:
@ObservationTracked
var test: String = ""
{
get {
access(keyPath: \.test)
return _test
}
set {
withMutation(keyPath: \.test) {
_test = newValue
}
}
}
...
@ObservationIgnored private var _test: String
Now you have hooks into setting the new value. So you can do something like this:
@ObservationIgnored #Flip this to ignored because you're doing your own manual getter/setter#
var test: String {
get {
access(keyPath: \.test)
return _test
}
set {
withMutation(keyPath: \.test) {
_test = newValue
#do your cool thing here#
}
}
}
...
@ObservationIgnored private var _test: String = "" #don't forget to move your initial value here#
So with very light testing this seemed to work as expected. YMMV. I think we'll just have to see if this is a pattern, or if Apple can provide us a way to annotate properties we want a didSet
hook for. Either way this might be the exact kind of use case we could write our own macro for. But I'd prefer if Apple solves this. I'm going to file a bug with Apple immediately to request they give us a built in solution. If we want to get it fixed, I think Apple needs to hear about and very soon so it still has a chance in getting in this year.