Anker USB Power Strip (10-in-1, 20W) (USBタップ 電源タップ AC差込口/USB-C/USB-A/延長コード 1.5m) 【PSE技術基準適合/USB Power Delivery対応 】MacBook PD対応 Windows PC iPad iPhone Galaxy Android スマートフォン ノートPC 各種 その他機器対応
¥2,990 (2025年4月28日 13:11 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)BIGBIG WON PC コントローラー LCDディスプレイ付き 1000Hzポーリングレート トリガー入力切替可能 PC/Switch/Android/iOS対応 2つ背面ボタン TURBO連射/HD振動機能付 mojhon aether ゲームパッド 有線/Bluetooth接続/2.4G無線接続可能
¥3,980 (2025年4月28日 13:11 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)USB C ケーブル 純正 1M 2本セット PD対応 60W急速充電 USBタイプc ケーブル USB-C & USBC データ転送 高耐久性 断線防止 映像出力不可 Type-c to Type-c コード for iPhone 16/15 Pro/Plus/Pro Max、for MacBook Pro/Air/IPad Pro/AirなどTypec機種対応
¥766 (2025年4月28日 13:05 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
こんにちは、こんばんは、kitakkunです。
Kotlin Conf 2024の以下のセッションで何度かSKIEについて言及されていたので、気になって調べた雑なメモです。
ほぼ公式ドキュメントの概略をまとめた内容で、詳細な内部実装までは本記事では言及しません。元が英文なのと、筆者のiOS周辺知識が不足しているので、一部間違ってたらコメントなどでご指摘ください。
SKIE = Swift Kotlin Interface Enhancer
発音はスカイ(sky)。
KMPで書き出されたObjective-CライブラリはSwiftからアクセスする際、様々な言語機能の制限を受ける。
Kotlin Native の Compiler Plugin を使って Xcode Framework を改変することで上記問題を回避しているらしい。
ざっくり以下をサポートしているらしい(https://skie.touchlab.co/features)。
- 列挙(enum、sealed class/interface)
- 関数(デフォルト引数、グローバル関数、インタフェースの拡張関数、オーバーロード)
- コルーチン(suspend関数、Flow)
- Swift Code Bundling
列挙
そのままだと網羅的な条件分岐が使えず、毎回 switch 文に default case を書かなければいけない。
SKIEはKotlinのenum classやsealed classをラップするSwiftのenumを作って対応している。
enum classはSKIEが生成したSwiftのラップ版に置き換えてくれるので特別な作業はいらないが、sealed classに関してはインスタンスが別クラスになってしまうので、Swift側ではonEnum(of:) を使ってKotlinのenumをSwiftのenumに変換して使う必要がある。
関数
デフォルト引数
デフォルト引数はObjective-Cがサポートしてない。SKIEはオーバーロードの関数宣言を全部生成することで実質的にデフォルト引数がある挙動を実現している。
ただし、やりすぎると目に見えてオーバーヘッドがでかくなるので、デフォルトでは無効になっているみたい。
グローバル関数
通常Kotlin側に定義されたグローバル関数(トップレベル関数)は、ファイル名に続けて呼ぶ必要がある。
FileKt.globalFunction(i: 0)
SKIEを導入するとFileKt.
の部分を省いてKotlinと同じように呼べるラッパーを作ってくれる。
インタフェースの拡張関数
グローバル関数と同じくファイル名書いて呼ばないといけなくてめんどいし、通常の関数みたいに引数でレシーバーを渡さないといけない。
FileKt.interfaceExtension(C(), i: 1)
SKIEはグローバル関数のときと同じくラッパーを作って(?)、通常の拡張関数と同じ感じで呼び出せるようにしてくれる。
オーバーロード
KotlinもSwiftも関数の引数型によるオーバーロード宣言が可能だが、Objective-Cはそれができない。
そのためKotlin Compilerは自動的に変数名を変えることによって衝突を防いでいる。
例えば以下のようなKotlinの関数があったとして、
fun foo(i: Int) {
}
fun foo(i: String) {
}
Swift側では通常以下のように呼び出すことになる(2つ目のfooの引数名がリネームされる)。
このようなリネームは本来Swiftには不要。SKIEはこれらの関数をそのまま使えるようにしてくれる。
コルーチン
suspend関数
Kotlin Compilerはsuspend関数をObjective-Cのコールバック関数としてコンパイルする。この関数は、Swiftからasync/await構文で呼び出すことができる。
ただし、これには以下の問題がある。
- Swiftではこれらのコールバック関数をキャンセルできない
- suspend関数を必ずメインスレッドから呼び出さなければならない
キャンセルができない問題に関しては、SKIEがKotlinとSwiftの両方のプラットフォームの非同期処理ランタイムを相互接続する機構を備えたasync関数を生成することで回避する。
また、実行スレッドの制限はSwiftのコンパイラーオプションを変更することで回避できるが、SKIEが勝手にいい感じにやってくれるらしい。
ドキュメントから拝借したものだが、例えば以下のKotlinのsuspend関数は
class ChatRoom {
suspend fun send(message: String) {
// Send a message
}
}
Swiftからは以下のように呼び出せるらしい(筆者はAndroidエンジニアなので詳しいことは知らないが、通常の非同期処理と同様の感覚で呼び出せる的なニュアンスの説明があったので、iOSエンジニア目線での違和感はそんなにないと思われる)
let chatRoom = ChatRoom()
let task = Task.detached { // Runs on a background thread
try? await chatRoom.send(message: "some message")
}
// Cancellation of the task also cancels the Kotlin coroutine
task.cancel()
Flow
Flowは通常のKotlinのインタフェースであり、Swiftの独自実装のAsyncSequenceと互換性がない。
直接的な互換APIもなく、キャストして使うこともできない。
SKIEはFlowをSwiftのAsyncSequenceを実装したカスタムクラスへとコンパイルする。
通常インタフェースの型引数(FlowのTの部分)はコンパイルで失われてしまうが、カスタムクラスにコンパイルする際にその情報は引き継がれるので、Swift側で特別に型のキャストが必要になることはないらしい。
Swift Code Bundling
SKIEを使うと、自分で書いたSwiftコードの一部をKotlinで作られたフレームワークの中にダイレクトに埋め込むことができる。
ここまで説明してきた内容は、Kotlinのコードが直接SwiftではなくObjective-Cとしてエクスポートされていたことに起因しているものが多い。
現在JetBrainsはKotlin Swift Exportの開発をアクティブに進めていて、これが実現するともう少しKMPがiOS開発者にとって身近な存在になっていくかもなので、期待したいところ。
本記事では公式ドキュメントで紹介されているSKIEの機能と役割について簡単に整理してみました。Kotlin NativeのCompiler Pluginということで、詳細な内部実装も気になるところです。
仮に今後Kotlin Swift Exportが安定化した際に、SKIEがどうなっていくのかは未知数ですが、Objective-Cとして書き出される現在の状態でも、割とSwiftから使いやすい状態にはできそうな印象です。
KMPの開発に取り組む際は、他の言語から見た使い勝手も無視できない要素だなとあらためて思いました。