Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Compose Multiplatform for iOS開発でぶつかった壁
Search
ねも
January 24, 2024
Technology
0
1.8k
Compose Multiplatform for iOS開発でぶつかった壁
2024/1/23に行われたZOZO Tech Meetup -Android-における発表資料です。
ねも
January 24, 2024
Tweet
Share
More Decks by ねも
See All by ねも
ノンプログラマのための ~アルゴリズムパズル プログラマのための数学パズル入門~
kohei_inoue
0
87
ノンデザイナーズ・デザインブックを読んだので名刺作ってみた
kohei_inoue
0
94
Compose Multiplatform for iOSで音声再生しようぜ!!
kohei_inoue
0
340
夏 × Jetpack Compose
kohei_inoue
0
89
Compose for iOS for ZOZOTOWN
kohei_inoue
0
1.8k
Other Decks in Technology
See All in Technology
事例に見るスマートファクトリーへの道筋〜工場データをAI Readyにする実践ステップ〜
hamadakoji
1
290
モブプログラミング再入門 ー 基本から見直す、AI時代のチーム開発の選択肢 ー / A Re-introduction of Mob Programming
takaking22
5
1.3k
[JAWS DAYS 2026]私の AWS DevOps Agent 推しポイント
furuton
0
140
[JAWSDAYS2026]Who is responsible for IAM
mizukibbb
0
430
Claude Codeが爆速進化してプラグイン追従がつらいので半自動化した話 ver.2
rfdnxbro
0
500
タスク管理も1on1も、もう「管理」じゃない ― KiroとBedrock AgentCoreで変わった"判断の仕事"
yusukeshimizu
5
2.6k
Claude Codeの進化と各機能の活かし方
oikon48
22
12k
20260311 ビジネスSWG活動報告(デジタルアイデンティティ人材育成推進WG Ph2 活動報告会)
oidfj
0
260
OCI技術資料 : コンピュート・サービス 概要
ocise
4
54k
オレ達はAWS管理をやりたいんじゃない!開発の生産性を爆アゲしたいんだ!!
wkm2
4
500
身体を持ったパーソナルAIエージェントの 可能性を探る開発
yokomachi
1
100
非情報系研究者へ送る Transformer入門
rishiyama
11
7.1k
Featured
See All Featured
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
140
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
480
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.8k
30 Presentation Tips
portentint
PRO
1
250
Rails Girls Zürich Keynote
gr2m
96
14k
Documentation Writing (for coders)
carmenintech
77
5.3k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
The Cult of Friendly URLs
andyhume
79
6.8k
Being A Developer After 40
akosma
91
590k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
290
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.1k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
Transcript
Compose Multiplatform for iOS ։ൃͰͿ͔ͭͬͨน XʢچTwitterʣ: https://twitter.com/nemo_855 GitHub: https://github.com/nemo-855 Qiita:
https://qiita.com/nemo-855 Android ΤϯδχΞ Ҫ্ ߊฏ / Ͷ 1
Ҫ্ߊฏ @nemo_855 XͰϑΥϩʔ͓ئ͍͠·͢🙏 • ZOZOTOWN։ൃຊ෦ ZOZOTOWN։ൃ1෦ Android2ϒϩοΫ • Α͏͘VIVANTΛݟ࢝Ί·ͨ͠ 2
ݸਓͰiOSͱAndroidΞϓϦΛ࡞͠·ͨ͠ʂ 3 iOS൛ Android൛
Jetpack Composeͱಉ͡ॻ͖ຯͰ iOSΞϓϦΛ࡞ΕΔͷ͍͢͝ʂʂ 4 iOS൛ Android൛
͚ͩͲɺɺɺ 5 iOS൛ Android൛
🍎 ࣍ 6 🍋 TextFieldΛλοϓͨ࣌͠ͷڍಈ 🍋 Android Context 🍋 ݖݶϦΫΤετͷਏΈ
🍍 TextFieldΛλοϓͨ࣌͠ͷڍಈ ͦͷ1 TextFieldΛλοϓͨ࣌͠ʹɺ ը໘֎ʹεΫϩʔϧͯ͠͠·͏ɻ 7
ComposeUiViewControllerͷconfigureҾʹ onFocusBehavior.DoNothingΛࢦఆ͢Εྑ͍ 🍍 TextFieldΛλοϓͨ࣌͠ͷڍಈ ͦͷ2 fun PostViewController( viewModel: PostViewModel, closePage:
() -> Unit, ): UIViewController { return ComposeUIViewController( configure = { onFocusBehavior = OnFocusBehavior.DoNothing }, ) { PostPage( context = IosKmpContext, viewModel = viewModel, closePage = closePage ) } } 8
໌֬ʹ͜ͷόάʹ͍ͭͯͷ GitHub issue͕ແ͔ͬͨ ↓ #3128, #3537, #3856ͳͲͷ ؔ࿈͢Δissue͔Βਪଌͯ͠ࢼߦࡨޡ͢ Δ͔͠ͳ͍ 🍍
TextFieldΛλοϓͨ࣌͠ͷڍಈ ͦͷ3 9
🍐 Android Context ͦͷ1 Compose Multiplatformͷڞ༗ϞδϡʔϧͰɺ ը૾Λѻ͏ࡍʹͲ͏ͯ͠ Android Context͕ඞཁʹͳΔ 10
🍐 Android Context ͦͷ2 11 actual fun Uri.getImageFlow(context: KmpContext): Flow<ImageBitmap>
{ return flow { val bitmap = this.getBitmapOrNull(context.contentResolver) if (bitmap != null) { emit(bitmap) } } } private fun Uri.getBitmapOrNull(contentResolver: ContentResolver): ImageBitmap? { return kotlin.runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val source = ImageDecoder.createSource(contentResolver, this) ImageDecoder.decodeBitmap(source) } else { MediaStore.Images.Media.getBitmap(contentResolver, this) } }.getOrNull()?.asImageBitmap() }
🍐 Android Context ͦͷ3 // commonMain expect abstract class KmpContext
// androidMain actual typealias KmpContext = android.content.Context // iosMain actual abstract class KmpContext object IosContext : KmpContext() kotlinlang SlackνϟϯωϧͰ հ͞Ε͍ͯͨख๏ ӈਤͷΑ͏ͳKmpContextΛ࡞͢Δ 12
🍐 Android Context ͦͷ3 // commonMain expect abstract class KmpContext
// androidMain actual typealias KmpContext = android.content.Context // iosMain actual abstract class KmpContext object IosContext : KmpContext() AndroidଆͰAndroidͷContextɺ iOSଆͰμϛʔͷContextΛ༻͢Δ 13
🍐 Android Context ͦͷ4 AndroidଆͷࣄΛڞ௨Ϟδϡʔϧʹແཧཧ ࣋ͪࠐΜͰ͍ΔͷͰෳࡶͳॲཧʹͳ͍ͬͯΔ Compose MultiplatformಠࣗͷਏΈ 14
ը૾ͷΞΫηεͷࡍʹͦΕͧΕͷOSͰݖݶ ΛϦΫΤετ͠ͳ͍ͱ͍͚ͳ͍͕ɺ ͦΕΒͷॲཧΛڞ௨Խ͢Δ͜ͱ͕͍͠ ↓ ίϯϙʔωϯτͷߏΛ͢Δ 🥭 ݖݶϦΫΤετͷਏΈ ͦͷ1 15
🥭 ݖݶϦΫΤετͷਏΈ ͦͷ3 val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) {
// ͜͜ͰݖݶͷεςʔλεʹԠͯ͡ذॲཧ } val permission = if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU) { READ_EXTERNAL_STORAGE } else { READ_MEDIA_IMAGES } launcher.launch(permission) PHPhotoLibrary.requestAuthorization { status in // ίίͰݖݶͷεςʔλεʹԠͯ͡ذॲཧ } Android iOS 16
🥭 ݖݶϦΫΤετͷਏΈ ͦͷ3 val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) {
// ͜͜ͰݖݶͷεςʔλεʹԠͯ͡ذॲཧ } val permission = if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU) { READ_EXTERNAL_STORAGE } else { READ_MEDIA_IMAGES } launcher.launch(permission) PHPhotoLibrary.requestAuthorization { status in // ίίͰݖݶͷεςʔλεʹԠͯ͡ذॲཧ } Android iOS ݖݶϦΫΤετͷॲཧ & ݖݶεςʔλεͷछྨ͕ҟͳΔͷͰɺ expect / actualͰڞ௨Խ͕͠ਏ͍ 17
commonMain 🥭 ݖݶϦΫΤετͷਏΈ ͦͷ4 androidMain iosApp Template Page View View
ը໘ભҠॲཧ ʢCompose Navigationʣ View ը໘ભҠॲཧ (SwiftUI) 18
commonMain 🥭 ݖݶϦΫΤετͷਏΈ ͦͷ5 androidMain iosApp Template Page View View
ը໘ભҠॲཧ ʢCompose Navigationʣ View ը໘ભҠॲཧ (SwiftUI) ɾը໘ͷঢ়ଶͷཧ ɾViewModelͷอ࣋ expect / actualͰڞ௨ԽͰ͖ͳ͍ॲཧ ྫʣ ݖݶϦΫΤετॲཧ 19
🥭 ݖݶϦΫΤετͷਏΈ ͦͷ6 @Composable fun PostView(closeView: () -> Unit) {
// ViewModelऔಘॲཧ val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) { // no-op } LaunchedEffect(Unit) { if (!PermissionChecker(context).isGallaryPermissionGranted()) { PermissionRequester().requestGallaryPermission(launcher) } } PostPage( context = context, viewModel = viewModel, closePage = closeView, ) } 20
🥭 ݖݶϦΫΤετͷਏΈ ͦͷ7 private struct PostView: UIViewControllerRepresentable { // লུ:
ϓϩύςΟͷॳظԽॲཧ func makeUIViewController(context: Context) -> UIViewController { if (!isGallaryPermissionGranted()) { requestGallaryPermission(completion: { isGranted in // no-op }) } return MainKt.PostViewController( viewModel: viewModel, closePage: closeView ) } // লུ: updateUIViewController, dismantleUIViewController } 21
͕ࣗͿ͔ͭͬͨนΛհ͢Δ͜ͱͰɺ ผͷਓ͕ಉ͡༰ͰࠔΒͳ͍Α͏ʹͳͬͯཉ͍͠ʂʂ 22
🍇 ࢀߟ ✓ https://github.com/JetBrains/compose-multiplatform/issues/3128 ✓ https://github.com/JetBrains/compose-multiplatform/issues/3537 ✓ https://github.com/JetBrains/compose-multiplatform/issues/3856 ✓ https://kotlinlang.org/community/
23
24