I have encountered a synchronization issue while developing my iOS app where two parts of a SwiftUI view graph disagree on the same @MainActor @Observable view model state. Imagine two views that access currentValue in their bodies. One shows currentValue, and the other shows newValue after running this line of view model code:
self.currentValue = newValue
After manually expanding the @ObservationTracked macro and adding let _ = Self._printChanges() to the relevant view bodies, it became clear that the stale part of the view graph runs its body and consumes the change notification in willSet and doesn't perform any subsequent updates after self._currentValue = newValue or didSet.
self._$observationRegistrar.willSet(self, keyPath: \.currentValue) // stale view is updated in will set
self._currentValue = newValue
self._$observationRegistrar .didSet(self, keyPath: \.currentValue) // stale view does not honor did set
This notion is reinforced by the fact that the obvious diagnostic fix works. If the issue is that change notification is consumed before the new value is available, then we can request a view update cycle later to resolve it:
self.currentValue = newValue
#warning("please send help")
self.withMutation(keyPath: \.currentValue, {})
Obviously, this is not a permanent fix. I’m just wondering whether this is a known Observation or SwiftUI bug. I found this issue on GitHub (`withObservationTracking` can miss concurrent/coincident updates · Issue #83359 · swiftlang/swift · GitHub), but I’m not sure whether it’s related. If I had a minimal reproduction example, I would have shared it.