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
SwiftUI + Kotlin Multiplatform 開発で見えた長所と短所
Search
swiftty
September 02, 2023
Technology
2
5k
SwiftUI + Kotlin Multiplatform 開発で見えた長所と短所
swiftty
September 02, 2023
Tweet
Share
More Decks by swiftty
See All by swiftty
Wantedly Visit での SKIE の導入と振り返り
swiftty
0
5
iOS 18 から追加された SwiftUI の傾向について調べてみる
swiftty
3
430
Flutter アプリのリリースフローを考える
swiftty
0
190
Meet BrowserEngineKit
swiftty
0
1.5k
Cloud-managed certificates へ移行した話
swiftty
0
340
同じアプリを Flutter と SwiftUI で書いてみる
swiftty
0
440
Swift Package Manager へ移行した話
swiftty
0
540
SwiftLint にコントリビュートする
swiftty
1
4.5k
SwiftUI でリスト要素のインプレッションを計測する
swiftty
0
480
Other Decks in Technology
See All in Technology
20250208_OpenAIDeepResearchがやばいという話
doradora09
PRO
0
170
5分で紹介する生成AIエージェントとAmazon Bedrock Agents / 5-minutes introduction to generative AI agents and Amazon Bedrock Agents
hideakiaoyagi
0
220
Building Products in the LLM Era
ymatsuwitter
10
4.4k
AndroidXR 開発ツールごとの できることできないこと
donabe3
0
110
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
500
Platform Engineeringは自由のめまい
nwiizo
4
1.9k
関東Kaggler会LT: 人狼コンペとLLM量子化について
nejumi
3
460
Data-centric AI入門第6章:Data-centric AIの実践例
x_ttyszk
1
370
スクラムのイテレーションを導入してチームの雰囲気がより良くなった話
eccyun
0
110
目の前の仕事と向き合うことで成長できる - 仕事とスキルを広げる / Every little bit counts
soudai
22
5.8k
バックエンドエンジニアのためのフロントエンド入門 #devsumiC
panda_program
16
6.5k
テストアーキテクチャ設計で実現する高品質で高スピードな開発の実践 / Test Architecture Design in Practice
ropqa
3
710
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
Site-Speed That Sticks
csswizardry
3
370
We Have a Design System, Now What?
morganepeng
51
7.4k
How to Ace a Technical Interview
jacobian
276
23k
Raft: Consensus for Rubyists
vanstee
137
6.8k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
BBQ
matthewcrist
86
9.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
540
Docker and Python
trallard
44
3.3k
The World Runs on Bad Software
bkeepers
PRO
67
11k
GraphQLとの向き合い方2022年版
quramy
44
13k
Building Better People: How to give real-time feedback that sticks.
wjessup
366
19k
Transcript
© 2023 Wantedly, Inc. SwiftUI + Kotlin Multiplatform 開発で 見えた長所と短所
iOSDC Japan 2023 スポンサーセッション Sep. 2 2023 - ウォンテッドリー株式会社 / 林達也
自己紹介 id/tatsuya_hayashi_ar swiftty © 2023 Wantedly, Inc. ウォンテッドリー株式会社 2023 年
3 月〜 Wantedly Visit の iOS アプリの開発
今日話すこと 前提 • iOS エンジニアで Kotlin Multiplatform (KMP) には触れたことがない •
過去のプロダクトは基本 UIKit で SwiftUI は部分的な導入程度 話すこと • KMP や SwiftUI での開発の際にどのような取り組みがあったかを紹介 ◦ プロフィールリニューアルについて ◦ SwiftUI 事例 ◦ KMP と Swift/SwiftUI の組み合わせ © 2023 Wantedly, Inc.
はじめに © 2023 Wantedly, Inc.
プロフィールリニューアル プロジェクト • 各プラットフォームでのプロフィール体験を 揃える • ウォンテッドリーではもともと KMP を採用し てマルチプラットフォームでの開発を行って
いた ◦ Android が先行していたため KMP 側の実装は完了していた 🎉 • SwiftUI の採用 🎉 © 2023 Wantedly, Inc. 引用: https://www.wantedly.com/companies/wantedly/post_articles/489565
SwiftUI の採用 • 今までも設定画面など部分的な導入はあっ た • 今回のリニューアルでは SwiftUI で 実現できるのかの検証も含めて始まった
© 2023 Wantedly, Inc.
KMP とは • Kotlin Multiplatform • ビジネスロジックを共通化 • UI は各プラットフォームで実装
© 2023 Wantedly, Inc. 引用: https://kotlinlang.org/lp/multiplatform/
KMP とは • Kotlin Multiplatform • ビジネスロジックを共通化 • UI は各プラットフォームで実装
© 2023 Wantedly, Inc.
ビジネスロジックの共通化 Reactor • 単方向データフローアーキテクチャを採用 ◦ View → Action → (Mutation)
→ State → View → … ◦ アプリケーション全体でひとつの状態管理ではなく集約されたビュー単位で状態管理 • Kotlin で定義されたクラスなので ObservableObject に適合していない ◦ 後付けで ObservableObject が要求する objectWillChange を 実装するのは大変 © 2023 Wantedly, Inc.
ビジネスロジックの共通化 Reactor • 単方向データフローアーキテクチャを採用 ◦ View → Action → (Mutation)
→ State → View → … ◦ アプリケーション全体でひとつの状態管理ではなく集約されたビュー単位で状態管理 • Kotlin で定義されたクラスなので ObservableObject に適合していない ◦ 後付けで ObservableObject が要求する objectWillChange を 実装するのは大変 © 2023 Wantedly, Inc. → Swift 側で Reactor をラップする
SwiftUI とReactor © 2023 Wantedly, Inc.
SwiftUI とReactor © 2023 Wantedly, Inc.
SwiftUI とReactor © 2023 Wantedly, Inc. → 以降は通常の SwiftUI と同じ
SwiftUI とReactor © 2023 Wantedly, Inc. → 以降は通常の SwiftUI と同じ
SwiftUI とReactor © 2023 Wantedly, Inc. → 以降は通常の SwiftUI と同じ
SwiftUI 事例 プロフィールヘッダー © 2023 Wantedly, Inc.
プロフィールヘッダー © 2023 Wantedly, Inc. UIKit でもよくある UI • コンテンツをスクロールするとヘッダーが縮む
• タブを切り替えたらヘッダーはそれに追従する
プロフィールヘッダー SwiftUI ではどうする? • ScrollView のスクロールを起点にレイアウトの制御を行いたい • SwiftUI の ScrollView
の問題 ◦ contentInset が調整できない ◦ オフセットを監視できない ◦ オフセットを変更できない © 2023 Wantedly, Inc.
プロフィールヘッダー SwiftUI ではどうする? • contentInset が調整できない → 空のビューでヘッダー分コンテンツの開始位置をずらす? • オフセットを監視できない
→ 子要素を GeometryReader で監視? • オフセットを変更できない → ScrollViewReader を使って scroll ならできる? • 最終的にオフセットをもとにヘッダービューの高さを変更すれば 当初のレイアウトを実現できそう 💭 © 2023 Wantedly, Inc.
プロフィールヘッダー © 2023 Wantedly, Inc.
プロフィールヘッダー © 2023 Wantedly, Inc. TabView を page スタイルで表示
プロフィールヘッダー © 2023 Wantedly, Inc. 各 content 内の ScrollView に高さ
0 で設置した ビューの位置をコンテンツの開始位置として anchorPreference で監視
プロフィールヘッダー © 2023 Wantedly, Inc. 各 content 内の ScrollView に高さ
0 で設置した ビューの位置をコンテンツの開始位置として anchorPreference で監視 overlayPreferenceValue でその位置をもとに ヘッダーの高さを算出しオーバーレイで重ねる
プロフィールヘッダー © 2023 Wantedly, Inc. オフセットが変化するたびに選択されたタブ以外の スクロール位置を scrollTo で同期させる
プロフィールヘッダー © 2023 Wantedly, Inc.
プロフィールヘッダー © 2023 Wantedly, Inc. → 思ったより素直なコードで実現できた 🎉
プロフィールヘッダー 良かった点 • 複雑なレイアウトを SwiftUI でシンプルに実現 ◦ UIKit なら数百行↑ 悪かった点
• ScrollView と List で挙動が変わる ◦ scrollTo の対象(ビュー単位、セル単位) • OS バージョンでの挙動の違いやパフォーマンスの観点でリリース間際まで格闘 ◦ 検証時は GeometryReader/onPreferenceChange を利用 ◦ safeAreaInset なども試したがその領域の奥へのインタラクションが反応しないなど問 題あり © 2023 Wantedly, Inc.
Xcode Previews © 2023 Wantedly, Inc.
Xcode Previews Wantedly Visit アプリ • Preview を積極的に活用して開発 ◦ 動作確認しやすいのでチームで自然とそうなった
• Feature Modules + KMP 構成(に移行中) ◦ ビジネスロジック(KMP)がビルド済みの XCFramework ◦ 依存の少ない新規 Profile モジュール • Preview 時は AnySwiftUIReactor に任意の State を設定してパターンを用意 © 2023 Wantedly, Inc.
Xcode Previews © 2023 Wantedly, Inc.
Xcode Previews © 2023 Wantedly, Inc.
Xcode Previews © 2023 Wantedly, Inc.
Xcode Previews 良かった点 • ビルド時間がほぼなく快適な体験 • 任意の State の注入によるパターンの確認しやすさ 悪かった点
• 任意の State を注入できるため、コンポーネントの適切な設計は 要検討 ◦ State のバケツリレー ▪ どこまでまとまったデータで扱うか、どこでプリミティブな値で扱うか © 2023 Wantedly, Inc.
KMP を Swift で扱う際の短所 © 2023 Wantedly, Inc.
KMP を Swift で扱う際の短所 • ネストされた型の階層の制限 • sealed class の網羅性チェック
© 2023 Wantedly, Inc.
KMP を Swift で扱う際の短所 • ネストされた型の階層の制限 • sealed class の網羅性チェック
© 2023 Wantedly, Inc.
ネストされた型の階層の制限 © 2023 Wantedly, Inc. KMP は Objective-C のモジュールを生成する
ネストされた型の階層の制限 © 2023 Wantedly, Inc. KMP は Objective-C のモジュールを生成する →
swift_name が複数階層をサポートしていない
ネストされた型の階層の制限 © 2023 Wantedly, Inc. Swift で見ると3階層以降はまとめられてしまう Swift だと型推論を活かして `.`
の左側は省略する ことが多い 階層が定義通りなら KMP の場合でも省略できるが …
KMP を Swift で扱う際の短所 • ネストされた型の階層の制限 • sealed class の網羅性チェック
© 2023 Wantedly, Inc.
sealed class の網羅性チェック © 2023 Wantedly, Inc. Swift では default
が必要になる
sealed class の網羅性チェック © 2023 Wantedly, Inc. Enum を再定義しコンパイルタイムで検知できるよう にインターフェースを用意
sealed class の網羅性チェック © 2023 Wantedly, Inc. Enum を再定義しコンパイルタイムで検知できるよう にインターフェースを用意
※ ライブラリ管理の移行が落ち着いたら自動生成などを検討 https://github.com/icerockdev/moko-kswift → 利用するときは網羅性チェックが効くように 🎉
まとめ KMP と SwiftUI • 100% SwiftUI でリニューアルを実現 🎉 •
KMP も SwiftUI の組み合わせも(癖はありつつ)体験は 👍 • Android も含めたモバイル開発チームの連携で大きくつまづくこともなかった 🤝 © 2023 Wantedly, Inc.
ご清聴ありがとうございました © 2023 Wantedly, Inc.
© 2023 Wantedly, Inc.