-
Notifications
You must be signed in to change notification settings - Fork 0
Bridging Swift Kotlin
Ali Sadeghi edited this page May 18, 2026
·
4 revisions
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
Kotlin interface in iosMain → Swift implements it in iosApp → Inject via Koin DI
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.
// <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/<Feature>Bridge.kt
interface <Feature>Bridge {
suspend fun execute(param: String): String
}// <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)) }
}// 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) }
}
}
}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())
}
}// <module>/src/iosMain/kotlin/{PKG_PREFIX}/<feature>/di/Module.ios.kt
actual val platformModule = module {
singleOf(::IOS<Feature>Provider).bind<<Feature>Provider>()
}// composeApp/build.gradle.kts
iosTarget.binaries.framework { export(project(":core:data")) }| 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 |
./gradlew :composeApp:embedAndSignAppleFrameworkForXcodeWhen 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
- 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