一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • Compose Multiplatformの可能性:KotlinでiOS・Android・デスクトップ統合開発

Compose Multiplatformとは

Compose Multiplatformは、JetBrainsが開発するKotlinベースのUIフレームワークです。Android向けに開発されたJetpack Composeの宣言的UIの概念を、iOS、デスクトップ、Webにまで拡張したものです。Kotlin Multiplatform(KMP)の上に構築されており、ビジネスロジックだけでなくUI層までコードを共有できる点が大きな特徴です。

筆者はFlutterやReact Nativeなど複数のクロスプラットフォームフレームワークを業務で使用してきましたが、Compose Multiplatformは特にKotlinエコシステムに精通したチームにとって魅力的な選択肢です。本記事では、その実力と現時点での課題を実装例とともに掘り下げます。

プロジェクトのセットアップ

プロジェクト構成

Compose Multiplatformプロジェクトは、KMPの標準的なディレクトリ構成に従います。共有コードはcommonMainに配置し、プラットフォーム固有の実装は各ソースセットに分離します。

// build.gradle.kts (shared module)
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose")
}

kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
jvm("desktop")

sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.components.resources)
}
androidMain.dependencies {
implementation(libs.androidx.activity.compose)
}
val desktopMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
}
}
}
}

エントリーポイントの設定

各プラットフォームのエントリーポイントから共有のComposable関数を呼び出します。

// commonMain - 共有App
@Composable
fun App() {
MaterialTheme {
var currentScreen by remember { mutableStateOf(Screen.Home) }
Navigator(currentScreen) { screen ->
currentScreen = screen
}
}
}

// androidMain
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { App() }
}
}

// desktopMain
fun main() = application {
Window(onCloseRequest = ::exitApplication, title = "MyApp") {
App()
}
}

共有UIの実装パターン

画面の構築

@Composable
fun TaskListScreen(
viewModel: TaskListViewModel,
onTaskClick: (Task) -> Unit
) {
val tasks by viewModel.tasks.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()

Scaffold(
topBar = {
TopAppBar(title = { Text("タスク一覧") })
},
floatingActionButton = {
FloatingActionButton(onClick = { viewModel.addTask() }) {
Icon(Icons.Default.Add, contentDescription = "追加")
}
}
) { padding ->
if (isLoading) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator()
}
} else {
LazyColumn(Modifier.padding(padding)) {
items(tasks) { task ->
TaskItem(
task = task,
onClick = { onTaskClick(task) },
onToggle = { viewModel.toggleTask(task.id) }
)
}
}
}
}
}

プラットフォーム固有処理の分離

// commonMain
expect class PlatformContext

expect fun getPlatformName(): String

// androidMain
actual class PlatformContext(val context: Context)
actual fun getPlatformName(): String = "Android ${Build.VERSION.SDK_INT}"

// iosMain
actual class PlatformContext
actual fun getPlatformName(): String = "iOS ${UIDevice.currentDevice.systemVersion}"

現時点での課題と注意点

  • iOS対応の成熟度:iOS向けはBeta段階であり、一部のAPIやアニメーションで制約がある
  • ビルド時間:KMPプロジェクトのビルドは通常のAndroidプロジェクトより時間がかかる傾向がある
  • ライブラリエコシステム:Jetpack Composeの全ライブラリがそのまま使えるわけではありません
  • デバッグ環境:iOS向けのデバッグはXcodeとの連携が必要になる場面がある

まとめ

Compose Multiplatformは、Kotlinという単一言語でiOS、Android、デスクトップのUIを統一的に開発できる画期的なフレームワークです。特にJetpack Composeに馴染みのあるAndroid開発者にとっては、学習コストを最小限に抑えてクロスプラットフォーム開発に参入できます。iOS対応のさらなる安定化が進めば、モバイルアプリ開発の有力な選択肢として定着していくでしょう。現時点では、新規の社内ツールや小中規模のアプリから試験的に導入し、知見を蓄積していくアプローチが現実的です。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア