+
# KMPObservableBridge
-
+### Kotlin state. Native SwiftUI.
+
+A Swift-first, lifecycle-safe observation bridge for Kotlin Multiplatform
+ViewModels, SKIE, KMP-NativeCoroutines, and SwiftUI.
+
+

[](https://swift.org)
-[](https://github.com/sonmbol/KMPObservableBridge/actions/workflows/swift.yml)
-[](LICENSE)
+[](#requirements)
+[](https://github.com/sonmbol/KMPObservableBridge/actions/workflows/ci.yml)
+[](LICENSE)
-KMPObservableBridge lets SwiftUI observe real Kotlin Multiplatform ViewModels
-without shadow Swift ViewModels. Local Swift macros create statically typed
-observation plans: no generated source files, selector discovery, swizzling,
-Objective-C interception, or undocumented SKIE ABI lookup.
+
```swift
@KMPStateObject private var profile = ProfileViewModel()
+
+var body: some View {
+ ProfileContent(
+ state: $profile.profileState,
+ searchText: $profile.searchText,
+ retry: profile.retry
+ )
+}
```
-Kotlin remains the source of truth. One macro declaration per ViewModel lists
-its exported state with ordinary Swift key paths, so a renamed or incompatible
-property fails the application build.
+No shadow Swift ViewModel. No copied business state. No runtime reflection,
+swizzling, selector discovery, or generated source file.
-## Requirements
+## Why KMPObservableBridge?
-- Swift 5.9+
-- iOS 15+, macOS 11+, tvOS 14+, or watchOS 7+
-- A KMP framework whose `StateFlow` properties are exposed as Swift
- `AsyncSequence`s, such as a framework enhanced by SKIE
+Kotlin remains the authoritative source of truth while SwiftUI receives native
+values, bindings, ownership semantics, and precise dependencies.
+
+| Capability | Behavior |
+| --- | --- |
+| Native ownership | `@KMPStateObject`, `@KMPObservedObject`, and `@KMPEnvironmentObject` mirror SwiftUI’s ownership language |
+| Field-level dependencies | On iOS 17+, only views that read an emitted projected field are invalidated |
+| Shared collection | Multiple SwiftUI wrappers share one collector set per Kotlin model |
+| Native projection | `$viewModel.state` returns the current Swift value without exposing `.value` |
+| Safe bindings | Writable Kotlin exports produce `Binding`; read-only StateFlows remain read-only |
+| Deterministic lifetime | Collection, callback, Combine, and NativeFlow cancellation follow SwiftUI identity storage |
+| Exporter isolation | SKIE and NativeCoroutines APIs live in separate package products |
+| Compile-time configuration | Macros validate imported ViewModel types and state key paths |
+
+