← All courses

Consuming Shared Code from Each App

🗓 May 31, 2026 ⏱ 2 min read

The shared module is just a dependency

To both apps, the shared module looks like a normal library — but the way each consumes it differs slightly. Understanding this removes the “magic” and makes KMP feel approachable.

Android: a Gradle dependency

This is the easy side. The Android app adds the shared module in Gradle and calls its Kotlin classes directly — same language, no bridging.

// androidApp/build.gradle.kts
dependencies { implementation(project(":shared")) }

// in a Compose screen / Android ViewModel
val repo = UserRepository(/* injected */)
val users = repo.getUsers()   // just Kotlin calling Kotlin

iOS: a native framework

For iOS, Gradle compiles the shared module (via Kotlin/Native) into a framework that Xcode links. In Swift you import it and call its types like any Swift library.

import shared   // the generated framework

let repo = UserRepository(api: api, db: db)
// suspend functions appear as async (with SKIE) or completion handlers
let users = try await repo.getUsers()

How Kotlin maps to Swift

  • Kotlin classes & data classes → Swift classes.
  • Kotlin suspend → Swift async (or a completion handler).
  • Kotlin Flow → Swift AsyncSequence (with SKIE) or a wrapper.
  • Sealed classes → Swift enums (with SKIE) for clean switch handling.

Tools like SKIE dramatically improve this mapping, making the shared API feel like idiomatic Swift.

The typical build flow

  1. You change Kotlin in the shared module.
  2. Android picks it up directly on the next build.
  3. For iOS, Gradle rebuilds the framework (often automated via a build phase in Xcode), and Swift sees the updated API.

What iOS developers need to know

They don’t need to write Kotlin — they consume the shared API like a library, focusing on building a great SwiftUI experience on top. A little familiarity with how Kotlin maps to Swift (above) is enough.

Common mistakes

  • Expecting Swift to use Flow/suspend with no bridging — add SKIE or wrappers.
  • Forgetting to rebuild the iOS framework after changing shared code.
  • Exposing overly “Kotlin-ish” APIs that feel awkward in Swift — design the shared surface with iOS consumers in mind.
Summary: Android uses the shared module as a plain Gradle dependency (Kotlin calling Kotlin); iOS links it as a native framework imported into Swift. Use SKIE to map suspend/Flow/sealed classes cleanly, and design the shared API to feel natural on both sides.