Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Wrap All iOS-Facing KMP Functions in runCatching

Avatar for Kuroruri Kuroruri
September 29, 2026

Wrap All iOS-Facing KMP Functions in runCatching

Avatar for Kuroruri

Kuroruri

September 29, 2026

More Decks by Kuroruri

Other Decks in Programming

Transcript

  1. 本日話す人 - 名前 くろるり - - 所属 - - teamLab

    Inc. 仕事 - iOSエンジニア アプリ開発効率化有志チーム 業務改善有志チーム
  2. Interoperability with Swift/Objective-C Errors and exceptions All Kotlin exceptions are

    unchecked, meaning that errors are caught at runtime. However, Swift has only checked errors that are handled at compile time. So, if Swift or Objective-C code calls a Kotlin method that throws an exception, the Kotlin method should be marked with the @Throws annotation, specifying a list of "expected" exception classes. When compiling to the Swift/Objective-C framework, non-suspend functions that have or inherit the @Throws annotation are represented as NSError*-producing methods in Objective-C and as throws methods in Swift. Representations for suspend functions always have an NSError*/Error parameter in the completion handler. When a Kotlin function called from Swift/Objective-C code throws an exception which is an instance of one of the classes specified with @Throws or their subclasses, the exception is propagated as an NSError. Other Kotlin exceptions reaching Swift/Objective-C are considered unhandled and cause program termination. suspend functions without @Throws propagate only CancellationException (as NSError). Non-suspend functions without @Throws don't propagate Kotlin exceptions at all. Note that the opposite reversed translation is not implemented yet: Swift/Objective-C error-throwing methods aren't imported to Kotlin as exception-throwing. See an example in the Kotlin-Swift interopedia. Kotlin Documentation, "Interoperability with Swift/Objective-C," Kotlin. https://kotlinlang.org/docs/native-objc-interop.html#errors-and-exceptions (accessed Sep. 14, 2026). 意訳 & 抜粋 • • • • 例外を throw する Kotlin メソッドを Swift か ら呼び出す場合、メソッド定義に @Throws アノテーションを付与する必要がある @Throws で指定された例外は伝搬、指定し てない例外はクラッシュを引き起こす @Throws が付与されていない suspend関 数はCancellationException のみを伝搬 @Throws が付与されていない非 suspend 関数はKotlin例外を一切伝搬しない
  3. 主な方法 1. iOS 側で強制ダウンキャスト 2. Generics を捨て return を 独自

    Result / Optional / enum などにする 3. UseCase の Result ではなくビジネスロジックの状態として扱う
  4. return を 独自 Result / Optional / enum などにする -

    non-suspend fun の場合はほぼこれ - 型定義が無制限に増加するデメリットはあるが、コンパイル時安全
  5. まとめ - KMP から iOS に意図せず例外が漏れるとクラッシュする - 例外を漏らさないよう最低限 runCatching 使うなどして対策を

    - ただし Result は iOS 的に Any? = ナンモワカランなので、 return 型を工夫するなり、 StateMachine 経由で非同期処理を使うなど するのがベター
  6. Wrap All iOS-Facing Kotlin Multi Platform Functions in runCatching, at

    least Mobile勉強会 ウォンテッドリー × チームラボ#25
  7. 余談 - AI に任せたら例外網羅もなんとかなるのでは? - 実際のところ例外を容易に throwしないよう実装はしてくる - 無課金一般ユーザーで利用可能な Gemini

    3.6 Flash でも割とちゃんとしてる - ので実際大抵なんとかなる - ただしコード非公開の SDK なんかは例外 throw 条件明記仕切ってないケースもあるので、 やはり「全部ありえる」想定にしておくのがベターだとは思う - - CancellationException どうすんねん? - suspend function は Interoperability にあるように伝搬してくれるので、こいつは throw しても平気 - runCatching で CancellationException なら re-throw する実装がよい @Throws(Throwable::class) では駄目なのか? - それも対策にはなり得る - が、Android のことを考えると明示的に成否がある function だと伝えたほうがベターだとは思う