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
5.5k
SwiftUI + Kotlin Multiplatform 開発で見えた長所と短所
swiftty
September 02, 2023
Tweet
Share
More Decks by swiftty
See All by swiftty
Wantedly Visit での SKIE の導入と振り返り
swiftty
0
53
iOS 18 から追加された SwiftUI の傾向について調べてみる
swiftty
3
800
Flutter アプリのリリースフローを考える
swiftty
0
320
Meet BrowserEngineKit
swiftty
0
1.8k
Cloud-managed certificates へ移行した話
swiftty
0
570
同じアプリを Flutter と SwiftUI で書いてみる
swiftty
0
580
Swift Package Manager へ移行した話
swiftty
0
690
SwiftLint にコントリビュートする
swiftty
1
4.6k
SwiftUI でリスト要素のインプレッションを計測する
swiftty
0
580
Other Decks in Technology
See All in Technology
「全員プロダクトマネージャー」を実現する、Cursorによる仕様検討の自動運転
applism118
22
12k
TS-S205_昨年対比2倍以上の機能追加を実現するデータ基盤プロジェクトでのAI活用について
kaz3284
1
230
AIがコード書きすぎ問題にはAIで立ち向かえ
jyoshise
1
130
Rustから学ぶ 非同期処理の仕組み
skanehira
1
150
初めてAWSを使うときのセキュリティ覚書〜初心者支部編〜
cmusudakeisuke
1
280
dbt開発 with Claude Codeのためのガードレール設計
10xinc
2
1.3k
いま注目のAIエージェントを作ってみよう
supermarimobros
0
360
ブロックテーマ時代における、テーマの CSS について考える Toro_Unit / 2025.09.13 @ Shinshu WordPress Meetup
torounit
0
130
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
10
75k
Automating Web Accessibility Testing with AI Agents
maminami373
0
1.3k
スクラムガイドに載っていないスクラムのはじめかた - チームでスクラムをはじめるときに知っておきたい勘所を集めてみました! - / How to start Scrum that is not written in the Scrum Guide 2nd
takaking22
2
200
テストを軸にした生き残り術
kworkdev
PRO
0
220
Featured
See All Featured
Agile that works and the tools we love
rasmusluckow
330
21k
Why Our Code Smells
bkeepers
PRO
339
57k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Site-Speed That Sticks
csswizardry
10
820
Balancing Empowerment & Direction
lara
3
620
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Rails Girls Zürich Keynote
gr2m
95
14k
What's in a price? How to price your products and services
michaelherold
246
12k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3k
A designer walks into a library…
pauljervisheath
207
24k
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.