Bind the ViewModel to Each UI
Connect shared state to Compose and SwiftUI.
Bind the ViewModel to Each UI is a free Kotlin Multiplatform Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Multiplatform Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Last Mile
Your shared ViewModel is ready. Now each native UI just needs to observe its state and forward user intents. That is the final wiring.
Compose Collects State
On Android, use collectAsState to turn the StateFlow into Compose state. Every emission recomposes the screen automatically.
val state by viewModel.state.collectAsState()Draw from That State
Your composable reads the collected state and renders it. The UI is now a pure function of the shared ViewModel's output.
Text(state.name)
if (state.isLoading) CircularProgressIndicator()Send Intents from Compose
Wire a button to onIntent. The user taps, Compose forwards the action, and the shared ViewModel decides what to do.
Button(onClick = {
viewModel.onIntent(HomeIntent.Refresh)
}) { Text("Refresh") }iOS Needs a Bridge
SwiftUI cannot collect a Kotlin Flow directly. A tiny observable wrapper bridges StateFlow into something SwiftUI can watch.
An ObservableObject Wrapper
Wrap the ViewModel in a Swift ObservableObject. It holds a published copy of the state and feeds SwiftUI updates.
class HomeObservable: ObservableObject {
@Published var state = HomeState(isLoading: false, name: "")
}Collect the Flow in Swift
Inside the wrapper, collect the Kotlin StateFlow and assign each value to the published property. SkieKit can also generate this for you.
Render in SwiftUI
The SwiftUI view observes the wrapper and reads state the same way. One shared truth, drawn in Apple's native style.
Text(observable.state.name)Send Intents from Swift
Buttons in SwiftUI call the wrapped ViewModel's onIntent too, so iOS taps flow into the exact same shared logic.
Button("Refresh") {
observable.viewModel.onIntent(intent: .refresh)
}Clear on Disappear
When a screen closes, call the ViewModel's clear() from each platform's lifecycle so the scope cancels and nothing leaks.
Same Brain, Two Faces
Both apps now share one ViewModel: identical state, identical decisions, only the rendering differs. That is KMP at its best. 🎉
Quick Check
Let's confirm how SwiftUI consumes a shared StateFlow.
Recap
Compose uses collectAsState; SwiftUI uses an ObservableObject wrapper. Both observe state and send intents to one shared ViewModel. 🚀
Frequently asked questions
Is the “Bind the ViewModel to Each UI” lesson free?
Yes — the full text of “Bind the ViewModel to Each UI” is free to read here on the web, and the Kotlin Multiplatform Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Kotlin Multiplatform Academy course, upgrade to CoddyKit PRO.
What will I learn in “Bind the ViewModel to Each UI”?
Connect shared state to Compose and SwiftUI. You practise Kotlin Multiplatform Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Multiplatform Academy?
No prior experience is required. Kotlin Multiplatform Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Bind the ViewModel to Each UI” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Multiplatform Academy lesson?
Yes. Every Kotlin Multiplatform Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- A Cross-Platform ViewModel Base
- Expose UI State as StateFlow
- Handle User Intents & Actions
- Bind the ViewModel to Each UI