Repository navigation
2.1.0
Fixes observed(_:) dropping property changes permanently.
Fixed
Changes landing during re-registration were lost. withObservationTracking cancels tracking the moment onChange returns, and re-registration was deferred into a Task. A mutation arriving in that window was never reported, and the stream stayed silent until some later mutation happened — if none did, the change was never delivered at all. Re-arming is now synchronous; only the read stays deferred, because onChange runs during willSet before the new value is stored.
Reads could beat the store on non-main-actor models. The deferred read was hardcoded to the main actor, which orders it after the store only when the mutation also happened there. A model on another actor could be read before its new value landed.
Added
observed(_:isolation:) and observedRelay(_:isolation:) take the actor that owns the model, defaulting to MainActor.shared. Pass your own actor if the model lives on one — the object must be mutated on whichever actor you pass.
Behaviour changes
- The stream is no longer de-duplicated. Every change is now reported, so a burst of rapid mutations can deliver the same settled value more than once. Consumers treating the stream as distinct-only should compare values themselves.
- Buffering is now explicitly
.unbounded— unchanged from the previous default, just stated, since a slow consumer on a hot property is more likely to see a backlog.
Existing @MainActor code needs no changes.
Not covered
An @Observable with no isolation at all, mutated from arbitrary threads, remains unsupported: there is no actor to order the read against. Give the model an isolation and pass it via isolation:.
Full changelog: 2.0.0...2.1.0