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
4.8k
SwiftUI + Kotlin Multiplatform 開発で見えた長所と短所
swiftty
September 02, 2023
Tweet
Share
More Decks by swiftty
See All by swiftty
Flutter アプリのリリースフローを考える
swiftty
0
94
Meet BrowserEngineKit
swiftty
0
1.3k
Cloud-managed certificates へ移行した話
swiftty
0
220
同じアプリを Flutter と SwiftUI で書いてみる
swiftty
0
330
Swift Package Manager へ移行した話
swiftty
0
270
SwiftLint にコントリビュートする
swiftty
1
4.4k
SwiftUI でリスト要素のインプレッションを計測する
swiftty
0
410
個人開発アプリでの Swift Macros 紹介
swiftty
0
500
Other Decks in Technology
See All in Technology
RubyのWebアプリケーションを50倍速くする方法 / How to Make a Ruby Web Application 50 Times Faster
hogelog
3
950
Amazon Forecast亡き今、我々がマネージドサービスに頼らず時系列予測を実行する方法
sadynitro
0
150
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
2
1.8k
iOS/Androidで同じUI体験をネ イティブで作成する際に気をつ けたい落とし穴
fumiyasac0921
1
110
AI前提のサービス運用ってなんだろう?
ryuichi1208
8
1.4k
プロダクト活用度で見えた真実 ホリゾンタルSaaSでの顧客解像度の高め方
tadaken3
0
260
A Tour of Anti-patterns for Functional Programming
guvalif
0
470
SkiaとImpellerについて
moriya0130
0
150
OCI Security サービス 概要
oracle4engineer
PRO
0
6.6k
Lambda10周年!Lambdaは何をもたらしたか
smt7174
2
140
【Startup CTO of the Year 2024 / Audience Award】アセンド取締役CTO 丹羽健
niwatakeru
0
1.8k
100 名超が参加した日経グループ横断の競技型 AWS 学習イベント「Nikkei Group AWS GameDay」の紹介/mediajaws202411
nikkei_engineer_recruiting
1
180
Featured
See All Featured
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Building an army of robots
kneath
302
43k
Imperfection Machines: The Place of Print at Facebook
scottboms
265
13k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
0
140
The Cost Of JavaScript in 2023
addyosmani
45
6.8k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.2k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
Designing Experiences People Love
moore
138
23k
How to train your dragon (web standard)
notwaldorf
88
5.7k
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.