Skip to content

Instantly share code, notes, and snippets.

@har5hit
Created August 3, 2022 20:25
Show Gist options
  • Save har5hit/6b0b34a91c38af3485e42e6cca2f5ebf to your computer and use it in GitHub Desktop.
Save har5hit/6b0b34a91c38af3485e42e6cca2f5ebf to your computer and use it in GitHub Desktop.
Calling kotlin suspend functions from Swift

Works

Suspend function can be called from swift on Main thread. Examples:

// Sample.kt
suspend fun add(a: Int, b: Int): Int {
    return a + b;
}

// Sample.swift
// Option - 1
SampleKt.add(a: 1, b: 2) { total, error in
    debugPrint("completionHandler: total \(total) error: \(error)")
}

// Option - 2
Task.init {
    do {
        let total = try await SampleKt.add(a: 1, b: 2)
            debugPrint("await: total \(total)")
        } catch {
            print("error \(error)")
        }
    }

Doesn't Work

Running suspend functions on background thread from swift doesn't work. Examples:

  • Backgroud thread using DispatchQueue
typealias Dispatch = DispatchQueue

extension Dispatch {
    static func background(_ task: @escaping () -> Void) {
        Dispatch.global(qos: .background).async {
            task()
        }
    }
    static func main(_ task: @escaping () -> Void) {
        Dispatch.main.async {
            task()
        }
    }
}

Dispatch.background {
    SampleKt.add(a: 1, b: 2) { total, error in
        debugPrint("Dispatch: total \(total) error: \(error)")
    }
}
Exception NSException * "Calling Kotlin suspend functions from Swift/Objective-C is currently supported only on main thread"
  • Running suspend function block from swift using coroutine from kotlin file.
// Sample.kt
fun <T> runWithCoroutine(dispatcher: CoroutineDispatcher, block: () -> T): Closeable {
    val job = Job()
    CoroutineScope(dispatcher + job).launch {
        block()
    }
    return object : Closeable {
        override fun close() {
            job.cancel()
        }
    }
}

// Sample.swift
SampleKt.runWithCoroutine(dispatcher: AppModule.dispatchers.io) {
    SampleKt.add(a: 1, b: 2) { total, error in
        debugPrint("runWithCoroutine: total \(total) error: \(error)")
    }
}
Exception NSException * "Calling Kotlin suspend functions from Swift/Objective-C is currently supported only on main thread"
@hiasel
Copy link

hiasel commented Jan 4, 2023

Starting with kotlin 1.7.20 its now possible to lift the restriction of calling suspend function only from the main thread.
Simply upgrade your project to use kotlinVersion 1.7.20 and add the following to your gradle.properties file:

kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none

Source: https://youtrack.jetbrains.com/issue/KT-51297/Native-allow-calling-Kotlin-suspend-functions-on-non-main-thread-from-Swift#focus=Comments-27-6106760.0-0

@har5hit
Copy link
Author

har5hit commented Jan 4, 2023

Thanks @hiasel, will check it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment