https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
d

Deniz Tumer

02/22/2024, 8:45 PM
Hi there, my team has been working on a multiplatform app for around a year now. We've run into a bit of a limitation that we can't seem to overcome. Was wondering if someone might be able to point us in the right direction. We're using Firebase for our authentication layer (using the respective cocoapod and java packages for the iOS and JVM targets) and have an expect/actual in front of the SDK to provide a common interface between the platforms. Inside of the Firebase library for iOS there's a few places where an NSException can be raised and it doesn't seem like there's a way to "catch" that exception either in the iosMain code or propagate the error out to the Swift side of our codebase outside of our shared Kotlin framework. Are we missing something simple here or is there a gap in Kotlin Native where NSException can't be implicitly wrapped into a Kotlin exception type that can be caught and re-thrown as needed?
r

russhwolf

02/22/2024, 8:55 PM
I'm not sure why you wouldn't be able to catch from the Kotlin side, but you can add a
@Throws
annotation to the relevant methods, and they'll be exported as
throws
so you can try/catch from Swift.
d

Deniz Tumer

02/22/2024, 8:56 PM
Yeah I tried that with
@Throws(Throwable::class)
but our app is crashing inside of the try/catch block. Seems like the NSException isn't being captured as an exception in Kotlin?
r

russhwolf

02/22/2024, 8:58 PM
yeah, sounds like something isn't wired up right but I couldn't guess at what the issue is without being in the codebase
d

Deniz Tumer

02/22/2024, 8:59 PM
I'm currently trying to opt into foreign exceptions to see if that could solve this? Seems like there's a beta api that needs to be opted into for wrapping NSExceptions in a ForeignException object?
Copy code
extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
j

Jeff Lockhart

02/22/2024, 8:59 PM
NSException
isn't possible to catch in Kotlin. It's also not possible in Swift.
NSError
can be propagated though.
NSError
is more commonly used for non-fatal errors in Objective-C, which can be handled in Kotlin.
d

Deniz Tumer

02/22/2024, 9:02 PM
Right I think the issue here though is that we're using an external SDK so I don't necessarily have control over whether the NSException is thrown. From the issue you posted it seems like these should still be propagated if marked with
@Throws
?
I can confirm that the following opt in works
Copy code
extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
This allows me to do the following in kotlin iosMain module:
Copy code
try {
  // some code that throws NSException
} catch (e: ForeignException) {
  // Catch!
}
👀 1
Seems like this is an api that's in Beta though. Not sure if it's just newer or if there's some known issues with it. Seems like it does exactly what I'm looking for
j

Jeff Lockhart

02/22/2024, 9:07 PM
Annotating a Kotlin function with
@Throws
will create an Objective-C header with an
NSError
parameter. But you're working in the opposite direction, needing to handle an Objective-C error in Kotlin. The typical pattern for this is for the Objective-C code to similarly allow for passing an
NSError
reference to propagate any error with.
d

Deniz Tumer

02/22/2024, 9:09 PM
Yeah I can't change the objective-c code though as it's a library owned by Google: https://github.com/firebase/firebase-ios-sdk Ideally yeah that makes sense that NSError would be easier to work with, just in this circumstance I don't have that flexibility
j

Jeff Lockhart

02/22/2024, 9:21 PM
That's great if the
objc-wrap
opt-in works around this for your use case here. It'd be good to communicate this on YouTrack so JetBrains is aware of your experience.
👍 1
Maybe Google wraps the Objective-C
NSException
throwing code to handle as
NSError
in Swift somehow. Otherwise this would similarly be an issue using the APIs from Swift.
Note that the opposite reversed translation is not implemented yet: Swift/Objective-C error-throwing methods aren't imported to Kotlin as exception-throwing.
To adapt Objective-C
NSError
producing code, for APIs that handle errors this way, I created this useful wrapper that converts
NSError
results into a Kotlin
Exception
and throws. Example usage.
👍 1
j

Jiri Bruchanov

02/22/2024, 9:47 PM
hey guys, where do I put the
extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
? if it's crashing from ios code directly, not from cocoapod 3rd party lib
d

Deniz Tumer

02/22/2024, 10:38 PM
@Jiri Bruchanov I put this into the build gradle for the shared module inside the pod definition. Here's an example from our codebase:
Copy code
pod("FirebaseAuth") {
    version = libs.versions.cocoapods.firebase.get()
    extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
}
🙌 1
j

Jiri Bruchanov

02/22/2024, 10:42 PM
@Deniz Tumer yeah that would work for your case... but I don't have any 3rd party cocoapod lib
d

Deniz Tumer

02/26/2024, 7:25 PM
Oh apologies yeah that is if the code breaks in external lib. If it's in code that you own I would probably use @Jeff Lockhart's suggestion above and replace usages of NSException with NSError
^ @Jiri Bruchanov
j

Jiri Bruchanov

02/26/2024, 7:28 PM
@Deniz Tumer Thanks, but I dont control the code. Its just regular ios api, not 3rd party lib.
d

Deniz Tumer

02/26/2024, 8:50 PM
Oh whoa yeah that's tough maybe there's a way to add something into the
iosMain
module to capture this? I'm not experienced enough with this yet to know where it goes. Are there compiler options we can use when setting up a kotlin source set?
j

Jiri Bruchanov

02/26/2024, 9:08 PM
I was wondering, if
objc_begin_catch
and
objc_end_catch
functions could be somehow useful, but I'm terrible with the cinterop, so not sure what, how to create argument for the begin_catch
1
blob shrug 1
3 Views