-
Notifications
You must be signed in to change notification settings - Fork 2
Architecture and Lifecycle
Kotlin StateFlow
├── synchronous current value ──→ SwiftUI body
└── SKIE AsyncSequence ─────────→ shared observation hub
↓
dependency invalidation
Kotlin remains the only business-state store. Swift stores revision cells, dependency keys, cancellation handles, and wrapper lifetime state.
On Observation-capable Apple platforms:
-
$model.fieldregisters a lazy field dependency. - An emission for that field updates its revision and the global revision.
- Unrelated allocated field cells are unchanged.
- Direct access through
modelregisters a global dependency. - A callback with no known field invalidates globally.
Earlier supported platforms use ObservableObject.objectWillChange, preserving
correct global invalidation.
A static macro observation plan uses a weak per-model registry. Wrappers for the same model lease one hub and do not create duplicate StateFlow collectors. The last listener releases the hub and cancels its collectors.
Explicit wrapper adapters define observation locally and should not be assumed to share that static plan.
The default .coalesced policy unions changed dependencies within one
main-actor turn and flushes each dependency once. .immediate delivers every
accepted emission.
When an observed wrapper receives another model:
- Pending invalidation work is cancelled.
- The previous observation lease is cancelled.
- A generation token advances.
- Existing dependencies invalidate once for the replacement.
- Late emissions from the previous model are rejected.
Task, Combine, callback, and NativeFlow adapters all terminate through the same idempotent cancellation abstraction.
Observation callbacks capture Swift stores weakly. Owning wrappers retain the Kotlin model for their SwiftUI identity; observed and environment wrappers do not claim disposal authority. A shared hub must disappear after its last lease so it cannot retain a Kotlin model across the ARC/GC boundary.