Kotlin Multiplatform Mobile を使ってiOS・Androidの処理を共通化する

### はじめに

[Kotlin Multiplatform Mobile がアルファ段階に移行 – Kotlin Blog \| JetBrains](https://blog.jetbrains.com/ja/kotlin/2020/09/kotlin-multiplatform-mobile-goes-alpha-ja/) ということなので、触ってみます

### インストール

[Preferences] -> [Plugins] -> Kotlin Multiplatform Mobile で検索

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16417/69cb99e2-17a4-c765-410f-a3309f0992f2.png" width="500">

### Kotlin Multiplatform Mobile の作成

[Create your first multiplatform application—Kotlin Multiplatform Mobile Docs](https://kotlinlang.org/docs/mobile/create-first-app.html) を参考にすすめます。

1. New Project から KMM Application を選択して各種Project名を作成
2. androidApp、iOSAppのビルド設定をする(iOS simulatorを使うためにはXcodeのインストールが必要なので注意

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16417/9cf9d13a-e2f5-6ac4-5ccf-7cca247d1ceb.png" width="500"> 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16417/743000de-0fc1-b6fb-f45a-90aaa782b58f.png" width="500">

プロジェクトを開くといくつかのサンプルコードが用意されています。
iOSでビルドすると、`shared/build/xcode-frameworks`にshared.frameworkが生成されます。（Run Scriptで`./gradlew :shared:packForXCode`が実行されている）

```Greeting.kt
class Greeting {
    fun greeting(): String {
        return "Guess what it is! > ${Platform().platform.reversed()}!"
    }
}
```

```commonMain/.../Platform.kt
expect class Platform() {
    val platform: String
}
```

```androidMain/.../Platform.kt
package com.example.kmmapplication.shared

actual class Platform actual constructor() {
    actual val platform: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}
```

```iOSMain/.../Platform.kt
import platform.UIKit.UIDevice

actual class Platform actual constructor() {
    actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16417/78f4688c-add6-fab4-8955-1dc3dfbc695e.png" width="500">

### 外部のプロジェクトからの参照する

Kotlin Multiplatform Mobileを作成すると同時にAndroid・iOSプロジェクトが作成されるがここでは、別のプロジェクトから使用してみます。
適当に以下のようにプロジェクトを作成します

KMM
　├ KMMIos
　├ KMMAndroid
　└ KMMApplication

#### iOSプロジェクトから参照する

KMM内のiOSプロジェクトではなく、別のiOSプロジェクトからKMMのコードを使用する方法です。
iOSプロジェクトからはフレームワーク経由での参照になります。普通のフレームワーク同様リンクすれば使用できます。（Framework Search Pathsの設定も忘れずに）
その際、iOSのプロジェクトにも、RunScriptにもFrameworkを生成するgradleの処理をいれておくと最新のモジュールを取得できるので追加しておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16417/7d2a307d-0569-3f4a-7d6e-aa0f022e5d92.png" width="500">

これで使えるようになります。

```ContentView.swift
import shared

struct ContentView: View {
    var body: some View {
        Text(Greeting().greeting())
    }
}
```

#### Androidプロジェクトから参照する

KMM内のAndroidプロジェクトではなく、別のAndroidプロジェクトからKMMのコードを使用する方法です。
Androidプロジェクトからは、gradle経由で参照します。

```settings.gradle
include ':app', ':shared'
project(':shared').projectDir = new File(settingsDir, '../KMMApplication/shared')
```

```build.gradle
dependencies {
  implementation project(':shared')
}
```

これで使えるようになります。

```MainActivity.kt
import com.example.kmmapplication.shared.Greeting

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val tv: TextView = findViewById(R.id.text_view)
    tv.text = Greeting().greeting()
  }
}
```