With the current proposal, there lacks a way for the caller to express that it no longer cares about the update from the previous withObservationTracking
(like a View is dismissed), or for the Observable object to express that changes are no longer possible (like when the underlying object is deallocated) so the observation tracking should stop.
Without those, it appears that it's not really possible for the implementation of withObservationTracking
to correctly release the resources when either situation happens (in fact it seems like the current implementation bundled with Xcode 15 beta 1 leaks the _ManagedCriticalState
on every SwiftUI view dismiss FB12294637).
Here is another example where a seemingly innocent use of the API can actually leak resources.
@Observable
class TestObject {
var value = 1
}
@MainActor
struct Renderer {
let viewModel = TestObject()
func render() {
withObservationTracking {
print(viewModel.value)
} onChange: {
Task { @MainActor in
schedule()
}
}
}
func schedule() {
render()
}
}
Here if someone creates a Renderer
object, and call render
on it, later set the reference of Renderer
to nil
, the object and associated resources will not get released.
Maybe the proposal should consider introducing some kind of scope for withObservationTracking
so the lifecycle of the observation can be better managed?