Source Set Layout
shared/src/
commonMain/kotlin/ // shared code, all targets
androidMain/kotlin/ // Android-only implementations
iosMain/kotlin/ // iOS-only implementations
commonTest/kotlin/ // tests run on every target
// build.gradle.kts (shared module)
kotlin {
androidTarget()
iosX64(); iosArm64(); iosSimulatorArm64()
sourceSets {
commonMain.dependencies {
implementation("io.ktor:ktor-client-core:2.3.x")
}
}
}
expect / actual
// commonMain
expect class PlatformStorage {
fun save(key: String, value: String)
fun read(key: String): String?
}
// androidMain
actual class PlatformStorage(private val ctx: Context) {
actual fun save(key: String, value: String) { /* SharedPreferences */ }
actual fun read(key: String): String? { /* ... */ }
}
// iosMain
actual class PlatformStorage {
actual fun save(key: String, value: String) { /* NSUserDefaults */ }
actual fun read(key: String): String? { /* ... */ }
}
Ktor Client
val client = HttpClient {
install(ContentNegotiation) { json() }
}
suspend fun getUsers(): List<User> =
client.get("https://api.example.com/users").body()
suspend fun createUser(u: User): User =
client.post("https://api.example.com/users") {
contentType(ContentType.Application.Json)
setBody(u)
}.body()
SQLDelight
-- Task.sq
CREATE TABLE Task (
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
done INTEGER NOT NULL DEFAULT 0
);
selectAll:
SELECT * FROM Task;
insertTask:
INSERT INTO Task(id, title, done) VALUES (?, ?, ?);
// Kotlin usage (generated API)
val tasks = database.taskQueries.selectAll().executeAsList()
Koin
val appModule = module {
single { HttpClient { install(ContentNegotiation) { json() } } }
single { UserRepository(get()) }
factory { UserViewModel(get()) }
}
fun initKoin() {
startKoin { modules(appModule) }
}
class UserRepository(private val client: HttpClient)
Compose Multiplatform
@Composable
fun UserList(users: List<User>) {
LazyColumn {
items(users) { user ->
Text(user.name, style = MaterialTheme.typography.bodyLarge)
}
}
}
// Same function, same file — renders on Android, iOS, and desktop.
Swift Interop
// Swift, importing the compiled shared framework
import Shared
let repo = UserRepository()
repo.fetchUser(id: 1) { user, error in
if let user { print(user.name) }
}
// Kotlin sealed class → Swift enum-like pattern match
switch onEnum(of: result) {
case .ok(let ok): print(ok.value)
case .err(let err): print(err.message)
}