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, TCA, KMPを用いた 新規動画配信アプリ 「ABEM...
Search
Tomu Obata
April 15, 2024
Technology
0
1k
少数チームで挑む: SwiftUI, TCA, KMPを用いた 新規動画配信アプリ 「ABEMA Live」の開発について
https://cyberagent.connpass.com/event/307949/
Tomu Obata
April 15, 2024
Tweet
Share
More Decks by Tomu Obata
See All by Tomu Obata
TCAとKMPを用いた新規動画配信アプリ 「ABEMA Live」の設計
tomu28
2
340
モジュール分割した開発での知見とテーマ切り替えやUICatalogについて
tomu28
1
890
Other Decks in Technology
See All in Technology
Python(PYNQ)がテーマのAMD主催のFPGAコンテストに参加してきた
iotengineer22
0
550
Chasing the White Whale of Open Source - ROI
mrbobbytables
0
110
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
2
460
The Rise of LLMOps
asei
9
1.8k
"とにかくやってみる"で始めるAWS Security Hub
maimyyym
2
100
RubyのWebアプリケーションを50倍速くする方法 / How to Make a Ruby Web Application 50 Times Faster
hogelog
3
950
Terraform Stacks入門 #HashiTalks
msato
0
360
IBC 2024 動画技術関連レポート / IBC 2024 Report
cyberagentdevelopers
PRO
1
120
Taming you application's environments
salaboy
0
200
オープンソースAIとは何か? --「オープンソースAIの定義 v1.0」詳細解説
shujisado
10
1.4k
SSMRunbook作成の勘所_20241120
koichiotomo
3
180
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
409
22k
Happy Clients
brianwarren
98
6.7k
A designer walks into a library…
pauljervisheath
204
24k
Writing Fast Ruby
sferik
627
61k
Embracing the Ebb and Flow
colly
84
4.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Designing the Hi-DPI Web
ddemaree
280
34k
Done Done
chrislema
181
16k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
Gamification - CAS2011
davidbonilla
80
5k
Code Reviewing Like a Champion
maltzj
520
39k
Transcript
株式会社サイバーエージェント 小幡 十矛 少数チームで挑む: SwiftUI, TCA, KMPを用いた 新規動画配信アプリ 「ABEMA Live」の開発について 2024/04/15 CA.swift
#19 1
・2021年、株式会社サイバーエージェントに新卒入社。 ・2023年4月までAmebaブログのiOSアプリを作成。 ・2023年5月から「ABEMA Live」iOSアプリの開発リードをしています。 ・WWDC 2024現地参加予定!🇺🇸 名前:小幡 十矛(Obata Tomu) 自己紹介
https://x.com/_tomu28 https://github.com/tomu28 2
POINT 01 サービス説明 POINT 02 実装機能 POINT 03 開発体制, スケジュール
POINT 04 iOS側の技術構成, 使用ライ ブラリ POINT 05 技術選定理由 POINT 06 開発Tips POINT 07 さいごに 目次 3
サービス説明 4
「ABEMA Live」では、「ABEMA」で配信されるアーティストのライブ、 イベント、スポーツ興行、舞台など多彩なペイパービュー (PayPerView)コンテンツを、海外からでも購入できます。 第一弾として世界最大級の格闘技団体・ONE Championshipの日本大会 をタイ、フィリピン、韓国にて同時生中継することが決定 https://www.onefc.com/jp/events/one165/ サービス説明 5
実装機能 6
ホーム/お知らせ/マイページ の3タブ構成 海外向け、PPV動画配信、 ログイン機能あり 実装機能 7
ユーザーログイン機能 ログイン アカウント登録 アカウント削除 ログインせずに使用する パスワードリセット 実装機能 8
ホーム 実装機能 9
番組詳細 実装機能 10
プレイヤー 実装機能 11
お知らせ一覧/詳細 実装機能 12
マイページ アカウントセッティング サービス概要 FAQ お問い合わせ ライセンスページ ログアウト 購入済み番組表示 → 番組詳細
実装機能 13
アプリ内課金 実装機能 14
その他 強制アップデート メンテナンスモード エラー画面 実装機能 15
その他 全画面タブレット対応 多言語対応(英語・タイ語・韓国語) Haptics feedback 実装機能 16
開発体制, スケジュール 17
2024/01/28に初回のイベントを実施 2023/10月までに基本的な機能を作り終え、 QA開始できる状態を目標に、開発を推進していた 2023/05から開発開始 開発体制としては、iOSエンジニア1~2人、Androidエンジニア1人 iOS、Android兼任1人 開発体制, スケジュール 18
iOS側の技術構成, 使用ライブラリ 19
VRT(pointfreeco/swift-snapshot-testing) KMP(Kotlin Multiplatform) TCA(The Composable Architecture) SPM(Swift Package Manager)でのライブラリ, モジュール管理
Feature単位でのマルチモジュール分割 プレイヤー周り:AVKit, UIKit。UIViewRepresentableを使い、UI側はフルSwiftUI Swift, SwiftUI, Swift Concurrency (iOS 16.6+) iOS側の技術構成, 使用ライブラリ 20
touchlab/SKIE vtourraine/AcknowList → ライセンス画面で使用 exyte/ScalingHeaderScrollView → 縮小する固定ヘッダーを備えたスクロール ビュー onevcat/Kingfisher siteline/swiftui-introspect
apple/swift-format realm/SwiftLint iOS側の技術構成, 使用ライブラリ 21
moko-resources → 画像は各OS毎の取得に変更 moko-kswift → SKIEに置き換え KMP-NativeCoroutines → SKIEに置き換え String
Catalog → KMP経由の文言取得に変更 現在は使っていないが一時期使っていたもの iOS側の技術構成, 使用ライブラリ 22
技術選定理由 23
1 メリット TCAを使用した理由 TCAに則って実装を進めることになるため、チームメンバー間で書き方のズレが少 なくなること KMP側でstateの値を更新するようにしても、iOS側でstateのbindやKMPのAction 発火、遷移周りの処理だったり、他ビューのAction伝搬などロジックもあるの で、TCAに乗っかった方が見通しが良くなる 2 許容したデメリット
開発当初はまだバージョンが0.x.x系ということもあり、推奨される書き方や破壊 変更に追従する必要があること → 開発途中で1.0.0がリリースされた 今後、メンバーが増減した時も対応しやすい 技術選定理由 24
TCA https://star-history.com/#pointfreeco/swift-composable- architecture&Date 技術選定理由 25
SKIEを使って、KMPで生成されたコードをswiftで扱いやすくする Presentation層のロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 26
Presentation層の ロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 27
Presentation層の ロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 28
Presentation層の ロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 29
Presentation層の ロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 30
Presentation層の ロジックまでKMP側で吸収 KMPで行っていること 技術選定理由 31
suspend funやflowをSwiftで扱いやすくなる default case削除(sealed class/interfaceをenumとして扱えるようにする) SKIEを使って、KMPで生成されたコードをSwiftで扱いやすくする KMPで行っていること 技術選定理由 32
SKIEを使って、iOS側で定義していたenumを削除した例 技術選定理由 33
SKIEを使って、default caseを削除した例 技術選定理由 34
TCAとKMPの連携(アカウン ト新規登録画面の場合) 技術選定理由 35
TCAとKMPの連携(アカウン ト新規登録画面の場合) 技術選定理由 36
TCAとKMPの連携(アカウン ト新規登録画面の場合) 技術選定理由 37
元々、String Catalogを使っていたがKMP経由の 文言リソースアクセスに変更 まず、String Catalog を使っていた理由 脱SwiftGen出来る No.05 No.03 純正なので、Appleの改善に追
従出来ること No.04 No.04 非常にシンプルな形で文言管 理、多言語対応出来る No.01 No.01 生成物を分かりやすい形でGit 管理出来る No.0 No.05 今後対応言語が増えても追加 対応しやすい No.02 No.02 Xcode上でString Catalogが見 やすい No.06 技術選定理由 38
XcodeよりEdit -> Convert → To String Catalogs...で、 Localizable.stringsをLocalizable.xcstrings(String Catalog)に Migrateする。もしLocalizable.xcstringsが存在するため、Migrate
出来ないとエラーが出る場合、元々存在していた Localizable.xcstringsを削除後、Migrateする。 Localizable.stringsを更新する 文字列リソースのCSV(localize-strings.csv)を編集する String Catalogの更新手順 元々、String Catalogを使っていたがKMP経由の 文言リソースアクセスに変更 技術選定理由 39
元々、String Catalogを使っていたがKMP経由の 文言リソースアクセスに変更 先ほどの手順でString Catalogを 更新するデメリット マスターとなるCSVに文言変更がある度、 Convertを手動でする必要がある。ショートカ ットを当てればかなり楽なので、個人的には 許容
String Catalogに記載されているKey名に補完を 使えないので、Key名は直接入力するかコピー して入力する必要がある。TypeSafeではない 例: Text("Key名", bundle: .module) 技術選定理由 40
別アプリでも同じ文言を使いたい場合、それぞれconvertしないといけない。共通コンポ ーネントUI確認用のStyleCatalogAppと、同じ文言を使う必要はなかったため問題はな かった。 恐らくAppleの想定的にはconvertはstringsファイルからの移行時に一度のみ使って、今 後はString Catalogの機能で文言追加推奨していると推測。ただ、今回はCSVをMaster Dataとして扱うので、この部分はAppleの推奨する開発フローとは若干それてしまう。 デメリット 元々、String Catalogを使っていたがKMP経由の
文言リソースアクセスに変更 技術選定理由 41
moko-resourcesとは moko-resourcesは、Android、iOS、Web向けのKotlin Multiplatform プロジェクトにおいて、リソース(文字列、色、画 像、フォント)のアクセスを容易にするライブラリです moko-resourcesを辞めた主な理由 技術選定理由 https://github.com/icerockdev/moko-resources 42
iOSer的にクリティカルな不具合もメンテされていないのはリスク 画像の言語別出し分けは標準機能として提供されていなそうだった moko-resourcesを辞めた主な理由 技術選定理由 43
画像に各言語毎の文言埋め込むパターン 今後、ビジネス要件的に入ってくる可能性が高いという背景も考慮 画像の言語別出し分けは標準機能として提供されていなそうだった moko-resourcesを辞めた主な理由 技術選定理由 44
SwiftUIのViewだけを組む時のスピードが落ちる。VRTのしやすさ にも影響 Xcode Previewsで多言語のプレビューを同時に行う機能がある が、それらも使えない Xcode Previewのクラッシュ不具合(クリティカル)が長期間放置 されている:https://github.com/icerockdev/moko- resources/issues/396 iOSer的にクリティカルな不具合もメンテされていないの
はリスク moko-resourcesを辞めた主な理由 技術選定理由 45
SwiftUIIntrospectでtabViewの 表示・非表示を切り替えるように しています。 swiftui-introspect 技術選定理由 46
SwiftUIIntrospectでtabViewの 表示・非表示を切り替えるように しています。 swiftui-introspect 技術選定理由 47
開発Tips 48
KMP側ロジックのデバッグ POINT 01 iOS側で意図しないレスポンスが返ってくるAPI があった時は、KMP側のRequest部分でKMPの ログライブラリであるNapierログを入れ、 Requestとして使っている値をXcode上に表示す る POINT 02
もしくは、Proxymanで通信を可視化して調査し ていました Tips 49
iOS側で意図しないレスポンスが返ってく るAPIがあった時は、KMP側のRequest部 分でKMPのログライブラリであるNapier ログを入れ、Requestとして使っている値 をXcode上に表示する KMP側ロジックのデバッグ Tips https://github.com/AAkira/Napier 50
KMP側ロジックのデバッグ 実機でしたら、ProxymanのiOS App を入れて特定のホストをフィルター表 示して確認 https://proxyman.io/posts/2021-10- 17-Getting-Started-With-Proxyman- For-iOS もしくは、Proxymanで通 信を可視化して調査してい
ました https://proxyman.io/ Tips 51
実機でしたら、ProxymanのiOS Appを入れて特定のホストをフィルター表示して確認 https://proxyman.io/posts/2021-10-17-Getting-Started-With-Proxyman-For-iOS Debugビルドだと、Napier.d で手元のXcodeよりログ見れます が、Release ビルドだとNapier.d 出さないようにしているた め、Proxyman で確認していました。
Proxyman Tips 52
以下のようにScheme変更することでシミュレーター自体の設定を 変更しなくてもタイ語が表示される状態でRun出来ます。 App Region: Thailand App Language: Thia 変更点: Tips
53
以下のコードが必要 StoreKit 2でIAPイベントのロギングをする場合 Tips https://firebase.google.com/docs/analytics/measure-in-app-purchases?hl=ja#swift 54
TCAに則り、NavigationStackStoreをAppViewというルートとなるViewで 使用して遷移処理を組んでいた 問題なく処理は行えていたが 理想はタブ毎などの適切な粒度で NavigationStackStoreの使用をすること Tips 画面遷移 55
IAP購入時、ログインしているAppleアカウント(Sandbox環境の場合は、 Sandboxアカウント)の国情報によって、通貨表記が変わるという仕様 タイで登録している 場合は฿ 日本で登録している 場合は¥ Tips 56
パッケージ, モジュール構成 依存の流れとしては、MobileAppFeatureパッケージで MobileAppCoreパッケージを読み込むような形となる 04/ 共通する処理はMobileAppCoreパッケージに入れるようにしている 03/ Feature moduleはMobileAppFeatureとしてまとめて置いたほうが、TV対応な ども視野に入れた時、モジュールの責務が明確になるため良いと考えた。
TV対応する時は、TVAppFeatureパッケージを作るイメージ。 02/ MobileAppFeatureとMobileAppCoreパッケージを定義 01/ Tips 57
1~2ヶ月ほど続けると、Androidエンジニアの方もPRを出せるようになりました 毎日のPR振り返りで各PRを全員で見る会を行っていました iOSエンジニアとAndroidエンジニアの歩み寄り Tips 58
iOSエンジニアはSwift, Androidエンジニアは Kotlin側のレビューをしっかり行う iOSエンジニアとAndroidエンジニアの歩み寄り Tips 59
iOSエンジニアはSwift, Androidエンジニアは Kotlin側のレビューをしっかり行う iOSエンジニアとAndroidエンジニアの歩み寄り Tips 60
iOSエンジニアはSwift, Androidエンジニアは Kotlin側のレビューをしっかり行う iOSエンジニアとAndroidエンジニアの歩み寄り Tips 61
タブレット対応 Tips 62
タブレット対応 Tips 63
強制アプデ 不確実性への対応必須な部分とそうでは ない部分を都度切り分け、現実的なスケ ジュールで進められるよう適切に交渉。 ビジネス側や契約の都合で変化する恐れ がある部分は、審査不要で対応出来るよ うにFeatureFlagを差し込むなど柔軟にア プローチする。 POINT 04
使い所や適用範囲は要検討ですが、申請 不要でリアルタイムで制御出来るのは便 利。 POINT 03 不測の事態に備えて、FeatureFlagを入れ ておくことは大事 POINT 02 リアルタイム Remote Configでフラグ管 理して必要であれば、リアルタイム反映 するようにしました POINT 01 Tips 64
設定を変更した後に再度審査に出さないと処理が進まなかった 日本以外の配信国を追加した際、 年齢制限「なし」のままだと処理が進まない 審査時、ハマったポイント 65
Tips UIはフルSwiftUI, ロジックはKMPで吸収する 構成で、Crash数は0をキープ出来ています 66
POINT 01 共通ComponentはStyle Catalog Appで見れるようにし て、デザイナー確認 POINT 02 Haptics Feedback
Tips 67
Haptics Feedback プレイヤーで5秒スキップ時 最も軽いlight feedbackを設定する ホーム面から「サムネイル画像」or 「Check This Event」タップし、番組 詳細面に遷移するとき
最も軽いlight feedbackを設定する 課金成功し、アイテムが更新された タイミング Appleが用意しているSuccess feedbackを設定 する Tips 68
Live Activity Strict Concurrency CheckingをComplete にしてSwift 6を見据え た対応を進めていく 今後の展望 69
想定外のことも往々にして起き続ける 例えば、途中でアプリ名が変わったり… 共通コンポーネントなどはサービスのコードネームにしておいたので、 影響範囲は最小で済みました サービスネームを直で使っている箇所はコードには存在しなかったので、 「アプリアイコン」 「翻訳のマスターとなるスプシのデータ」「Keyが変わった場合その部分の修正」のみ 何があるか分からない 新規開発 70
CHECK 大切にしていた心構え 必要な要件と、1stリリースでは やらないことを明確にして進める 意識 完全新規の0→1は初めて。 CHECK 自分でとにかく触って、問題が あったら直してを繰り返す 本当に使いやすいアプリになって
いるか。プロダクトの品質を意識 まず作り切るのは大事だが、 良いアプリを作る視点 新規開発 71
さいごに 72
今回は開発全般について、特に概念的な部分を多く取り上げまし た。4/25ではTCA・KMPのアーキテクチャ構成での開発導入がしや すくなるように、関連する簡易的なサンプルプロジェクトを作成 し、ご紹介する予定です。 iOSアプリのアーキテクチャ設計~TCA実践編~ https://findy.connpass.com/event/315494/ 4/25も登壇するので、そちらもご確認いただけますと嬉しいです! 最後までご清聴いただきありがとうございました!! 73