Hi Everyone, I have a suspending function in my K...
# coroutines
k
Hi Everyone, I have a suspending function in my KMP module that looks like this
Copy code
@Throws(
        CancellationException::class,
        UnauthorizedError::class
    )
    suspend fun login() {
        runBlocking {
            val fakeWaitingTime = 300L
            delay(fakeWaitingTime)
        }
    }
Then if I try to execute that login function inside Swift concurrency context like this
Copy code
Task {
    try? await Auth().login()
}
It will crash with this error:
Copy code
Function doesn't have or inherit @Throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError.
It is considered unexpected and unhandled instead. Program will be terminated.
Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared
I am using this version of coroutines
Copy code
const val coroutines = "1.6.0-native-mt"
Is there any work around for this? Thank you.
j
runBlocking
should not be used inside suspend functions. Why do you need it here?
☝️ 1
k
That was to silence another error previously 😅
🤔 1
Initially I don’t use runBlocking, but I got this error on iOS
Copy code
It is considered unexpected and unhandled instead. Program will be terminated.
Uncaught Kotlin exception: kotlin.IllegalStateException: There is no event loop. Use runBlocking { ... } to
j
Then you should use
runBlocking
from the most top-level place that calls suspend functions, but not from inside suspend functions themselves
k
But the function will be consumed from platform side (iOS, Android, macOS) … I can’t do runBlocking from iOS and macOS. Btw do you think
kotlin.native.IncorrectDereferenceException
is due to the runBlocking ?
j
I'm not very well versed in Kotlin/Native, but if it's called from platform side, then I think it shouldn't be
suspend
. You should remove the
suspend
modifier, and use
runBlocking
to call suspend functions in a blocking way
👍 1
If you still get the error after that, then I don't know. Maybe you can ask #kotlin-native
k
Thanks for your replies 🙏
r
Based on the error messages it looks like the non
native-mt
version is being used. Could you try to force the usage of the
native-mt
version as described here?
I’m not very well versed in Kotlin/Native, but if it’s called from platform side, then I think it shouldn’t be suspend . You should remove the suspend modifier, and use runBlocking to call suspend functions in a blocking way
You can actually use
suspend
functions from ObjC/Swift. These
suspend
functions are exported to ObjC as completion handler functions. Swift will in turn “import” those as
async
functions. Though it’s import to keep in mind that the actual function isn’t a real Swift
async
function, meaning it doesn’t support cancellation. If you would like to use
suspend
functions from Swift, you can take a look at my library KMP-NativeCoroutine which solves the limitations like missing cancellation support.
j
@Rick Clephas TIL, thanks!
👍🏻 1
k
Hi @Rick Clephas thanks for the insight. Will definitely check out your library. After further investigation, what contribute the issues that I encountered is the way I use Koin in my project. 🤔 So I do the startKoin when SwiftUI app is initialized and inside the onCreate function of my android. Which is happening on main thread. Then I have component like this
Copy code
class Authenticator {
  private val store: AuthStore by inject()

  suspend fun login() {}
}
then I try to use it in my Swift code like this
Copy code
Task {
  do {
    try await Authenticator().login
  } catch {}
}
Since code inside Task is executed NOT in main thread then the error happened.
r
Yeah for that to work with the "old memory model" those classes should be frozen.
277 Views