Was there any further discussion regarding a trailing edge variant of the API, @Philippe_Hausler?
There seems to be a genuine need here. If Observable is to be a Swift language type – rather than just a data flow accessory for SwiftUI – it seems like a big omission not to include it.
The willSet
variant is great for allowing SwiftUI to perform its 'before changes' render pass and schedule its 'after changes' render pass for the end of the current event loop cycle, but for anything else that needs to happen between these two points – we're stuck.
Really, the onChange
parameter of the withObservationTracking(_:onChange:)
function should be called willChange
to better reflect the semantics of the API.
A participant in the old pitch thread laid out their frustration with the current API:
As I summarised in the pitch thread, the two recommendations we have right now are to a) use computed properties, or b) use this pattern:
However, method A suffers from unnecessary view refreshes, while method B suffers from an async hop i.e the observation event happens after the 'after changes' SwiftUI snapshot. It misses SwiftUI's deadline for changes in the current transaction. It's also for this reason that an asynchronous sequence based API wouldn't help us here either.
To make this work how we want it, we really need Observable to generate trailing edge (didSet
) synchronous notifications.
This would allow dependent observers to make any changes they need to make within SwiftUI's deadline for the current event loop.
It doesn't need to be anything huge for this version of the proposal, something as simple as changing withObservationTracking(_:onChange:)
to withObservationTracking(_:willChange:didChange:)
could lay the foundation.