Skip to content

Bridging Swift Kotlin

Ali Sadeghi edited this page May 18, 2026 · 4 revisions

Bridging Swift-Kotlin Skill

Bridge Swift to Kotlin Multiplatform via Interface Injection. Use this skill when integrating iOS SDKs, calling Swift from Kotlin, accessing iOS-only APIs, or implementing biometrics / payments / camera / native frameworks.

Auto-activates when the user mentions "Swift bridge", "iOS integration", "native SDK", "biometrics", "payments", "camera".

Architecture reference: .claude/skills/_shared/patterns.md

Pattern

Kotlin interface in iosMain → Swift implements it in iosApp → Inject via Koin DI

Critical: Swift Inheritance

Swift class inherits from <ModulePrefix><InterfaceName>:

Module Kotlin interface Swift inherits
core:data RecaptchaBridge DataRecaptchaBridge
feature:auth AuthBridge AuthAuthBridge

Use Xcode autocomplete (Ctrl+Space) to find the exact protocol name.

Implementation Steps

1. Bridge interface (iosMain)

// <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/<Feature>Bridge.kt
interface <Feature>Bridge {
    suspend fun execute(param: String): String
}

2. Provider (iosMain)

// <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/IOS<Feature>Provider.kt
class IOS<Feature>Provider(private val bridge: <Feature>Bridge) : <Feature>Provider {
    override suspend fun execute(): Either<String> =
        try { Either.Success(bridge.execute("param")) }
        catch (e: Exception) { Either.Failure(ErrorModel.Exception(e)) }
}

3. Swift implementation (iosApp)

// iosApp/iosApp/<Feature>/<Feature>BridgeImpl.swift
import ComposeApp

class <Feature>BridgeImpl: <ModulePrefix><Feature>Bridge {
    func execute(param: String, completionHandler: @escaping (String?, Error?) -> Void) {
        Task {
            do { completionHandler(try await nativeOperation(param), nil) }
            catch { completionHandler(nil, error) }
        }
    }
}

4. DI Connection

MainViewController.kt (composeApp/src/iosMain/):

fun MainViewController(bridge: <Feature>Bridge) = ComposeUIViewController(
    configure = { initKoin { modules(module { single { bridge } }) } }
) { App() }

ContentView.swift (iosApp/iosApp/):

struct ComposeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        MainViewControllerKt.MainViewController(bridge: <Feature>BridgeImpl())
    }
}

5. Register provider (iosMain)

// <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/di/Module.ios.kt
actual val platformModule = module {
    singleOf(::IOS<Feature>Provider).bind<<Feature>Provider>()
}

6. Export module

// composeApp/build.gradle.kts
iosTarget.binaries.framework { export(project(":core:data")) }

Signature Mapping

Kotlin Swift
suspend fun foo() func foo(completionHandler: @escaping (Error?) -> Void)
suspend fun foo(): T func foo(completionHandler: @escaping (T?, Error?) -> Void)
Int Int32
Long Int64
Boolean (return) KotlinBoolean
Boolean (param) Bool

Validation

./gradlew :composeApp:embedAndSignAppleFrameworkForXcode

Spec Integration

When you add a bridge to an existing feature, the skill:

  • Checks for .claude/docs/{feature}/spec.md
  • If a spec exists, drafts spec updates for the new bridge interfaces
  • Updates the spec's Integration Points section after the build succeeds

Checklist

  • Interface in <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/
  • Provider wraps in try-catch returning Either<T>
  • Swift inherits <ModulePrefix><InterfaceName>
  • Completion handler signature matches exactly
  • MainViewController accepts + registers bridge
  • ContentView passes implementation
  • Module exported in composeApp/build.gradle.kts
  • Build: ./gradlew :composeApp:embedAndSignAppleFrameworkForXcode

Back to Skills

Clone this wiki locally