Translated into callback, experimentally - into async / await. Libraries like SKIE and KMP-NativeCoroutines can be used to improve the interop and provide cancellation support.
Let's describe a class that uses Kotlin suspend
functions:
data class Thing(val item: Int)
class ThingRepository {
suspend fun getThing(succeed: Boolean): Thing {
delay(100.milliseconds)
if (succeed) {
return Thing(0)
} else {
error("oh no!")
}
}
}
On the Swift side, the suspend function turns into a completion handler.
ThingRepository().getThing(succeed: true, completionHandler: { thing, error in
// do something
})
With Swift 5.5, an experimental opportunity has appeared to map suspend functions as async/await.
Task {
do {
let thing = try await ThingRepository().getThingSimple(succeed: true)
print("Thing is \(thing).")
}
catch {
print("Found error: \(error)")
}
}
However, neither these approaches have cancellation support. Even if the Task is cancelled, nothing happens. The suspend function will return as usual.
Task {
do {
let thing = try await ThingRepository().getThingSimple(succeed: true)
print("Thing is \(thing).") // This will be printed: Thing is Thing(name=Thing).
}
catch {
print("Found error: \(error)")
}
}.cancel() // Just a stub
KMP-NativeCoroutines is a library that can improve the interop and provides cancellation support. It is compatible with async/await, Combine, and RxSwift approaches to concurrency on iOS.
In Kotlin it is:
@NativeCoroutines
suspend fun getThing(succeed: Boolean): Thing {
delay(100.milliseconds)
if (succeed) {
return Thing(0)
} else {
error("oh no!")
}
}
In Swift:
Task {
do {
let result = try await asyncFunction(for: ThingRepository().getThing(succeed: true))
print("Got result: \(result)")
} catch {
print("Failed with error: \(error)")
}
}
Please follow the setup instructions in the KMP-NativeCoroutines documentation for the Gradle setup instructions.
In Swift:
Task {
do {
let result = try await asyncFunction(for: ThingRepository().getThing(succeed: true))
print("Got result: \(result)")
} catch {
print("Failed with error: \(error)")
}
}.cancel()
This will cause the suspend function to fail with a CancellationError.
SKIE is also improves the interop and provides cancellation support. SKIE is directly compatible with async/await, and with Combine and RxSwift using adapters.
In Kotlin it is the same as the original:
suspend fun getThing(succeed: Boolean): Thing {
delay(100.milliseconds)
if (succeed) {
return Thing(0)
} else {
error("oh no!")
}
}
In Swift:
Task {
let result = try await ThingRepository().getThing(succeed: true)
print("Got result: \(result)")
}
Please follow the setup instructions in the SKIE documentation for the Gradle setup instructions.
In Swift:
Task {
let result = try await ThingRepository().getThing(succeed: true)
print("Got result: \(result)")
}.cancel()
The Task is cancelled and nothing is printed.