A Kotlin Multiplatform to-do list app with SwiftUI and Compose UI frontends
🎶
Making a list
Checking it twice
Gonna try out declarative UIs
🎵
I'm just starting to learn my way around both Compose and SwiftUI so the code here can probably be improved on.
The core logic in the shared
module is implemented via SqlDelight
in ToDo.sq. This is exposed in a Kotlin API
by ToDoRepository.
In addition to pure common code, there are some iOS-specific helpers. Since suspend functions and Flow
s aren't
available to Swift, FlowAdapter is a
slightly modified version of the pattern I presented in
my Working with Kotlin Coroutines and RxSwift
blog post. A wrapper
class ToDoRepositoryIos then
exposes iOS-friendly versions of ToDoRespository
's API.
Unit tests verify the happy path for both repository classes, making use of
the Turbine library for testing Flow
s. Not a whole lot new there if you're used
to testing KMP code, but they're there to look at nonetheless.
The Android app in the androidApp
modules is a single
activity ToDoActivity which injects
a ToDoRepository
into composable views defined
in ToDoComposables.kt. There is a fully
interactable preview function ToDoListPreview()
which exercises the UI without any dependence on the shared code by
manually wiring in-memory state
The iOS app in the iosApp
directory consumes the repository in SceneDelegate.swift,
and renders it via SwiftUI views defined in ToDoViews.swift. There is a fully
interactable preview view defined in ToDoList_Previews
which exercises the UI without any dependence on the shared
code by manually wiring in-memory state.
The SwiftUI code makes use of some Combine helpers defined in CombineAdapters.swift
in order to translate FlowAdapter
to a Published
value that SwiftUI can subscribe to. It also converts the Kotlin
ToDo
class to a Swift ToDo
struct via utilities in ToDo.swift. This better matches typical
Swift development practices, and it means that the SwiftUI views have no direct dependence on the Kotlin code, which
apparently helps the preview work better.