Slide 1

Slide 1 text

©MIXI UICollectionViewのAPIを活用して シンプルなコードにリファクタリングする Vantageスタジオ みてね事業部 プロダクト開発グループ アプリ開発チーム 佐藤 光

Slide 2

Slide 2 text

©MIXI 自己紹介 ● 佐藤 光 (@hicka04) ● 株式会社MIXI みてね事業部 ○ 2021/11 中途入社 ● 二児の父 ● 「家族アルバム みてね(以下 みてね)」の1ユーザー ● 好きなもの ○ ラーメン ○ ポケモン 2

Slide 3

Slide 3 text

©MIXI アジェンダ ● 「家族アルバム みてね」とは ● リファクタリング対象と選んだ理由 ● リファクタリングの進め方 ● まとめ 3

Slide 4

Slide 4 text

©MIXI 「家族アルバム みてね」とは

Slide 5

Slide 5 text

©MIXI 「家族アルバム みてね」とは ● 家族で子供の写真を簡単に共有できるサービス ● 「世界中の家族の”こころのインフラ”を作る」 をミッションに掲げ、現在7言語対応 ● 利用者数が1,500万人(※)を突破(2023年3月現在) ママやパパの「半数」が使うアプリに 5 ※iOS・Android™ アプリ登録者数、ブラウザ版登録者数の合計

Slide 6

Slide 6 text

©MIXI リファクタリング対象と選んだ理由

Slide 7

Slide 7 text

©MIXI リファクタリング対象 ● アルバムタブ ● メディアを一覧できる画面 ● ページの種類 ○ 月ごとのメディア ○ コレクション (1秒動画などのコンテンツ ) ● 左右スワイプ or 上部のページタップで遷移 7

Slide 8

Slide 8 text

©MIXI アルバムタブを選んだ理由 ● 2022/4~ 開発体制をドメインチーム制に変更 (※) ○ アルバムの基本機能 (メディアのアップロード/閲覧など) ○ メディアを使った商品 ● アルバムタブに対して手を入れる機会が増えている ● 課題: リリース当初から継ぎ足しのコードが多い ○ いいものを早く届けるのが困難で、どこかで妥協が発生する ■ 修正に多くの工数がかかるのを許容 ■ 工数がかからないように仕様を調整 ○ 画面崩れが発生しやすくなっている 8 ※2022年版 みてねを支えるプロダクト開発体制

Slide 9

Slide 9 text

©MIXI リファクタリングの進め方

Slide 10

Slide 10 text

©MIXI 現状の課題を洗い出し ● StoryboardでUI作成 ○ コードレビューがしやすいコードでのレイアウトを推奨 ● ViewControllerにロジックが存在 ○ テストコードが書きづらい ● CollectionView ○ CollectionViewLayoutを使った地道なFrame計算 ○ reloadData で全件更新 ○ セル利用時に非型安全 ● など… 10

Slide 11

Slide 11 text

©MIXI CollectionView周りの解決方法の検討 ● CollectionViewLayoutを使った地道なFrame計算 ○ → Compositional Layouts (iOS 13 +) ● reloadData で全件更新 ○ → Diffable Data Source (iOS 13 +) ● セル利用時に非型安全 ○ → Cell Registration (iOS 14 +) 11 ※2023年3月時点でiOS14以上をサポートしているため、現状使える API限定

Slide 12

Slide 12 text

©MIXI なぜSwiftUIではないのか ● みてねでSwiftUIは未導入 ○ 導入検討中なので、今後活用していきたい ● iOS14以上で使えるSwiftUIのAPIでは若干機能不足 ○ UIだけであればほとんど実装可能そう ○ ScrollViewのoffsetを細かく調整する等は難しそうで 今回のユースケースに合わない 12

Slide 13

Slide 13 text

©MIXI Compositional Layouts (iOS 13 +) ● Section / Group / Item を組み合わせて構造化 ○ 宣言的にレイアウトを作ることができる ● サイズ指定 ○ 親のN%のサイズ ■ fractionalWidth / fractionalHeight ○ Self Sizing ■ estimated ● 位置指定 ○ Groupの並び horizontal / vertical / custom 13

Slide 14

Slide 14 text

©MIXI Diffable Data Source (iOS 13 +) ● 更新前後のデータ(snapshot)を比較して差分を取り 必要なセルのみリロードできる ● 1つのメソッドでデータ更新完結 ○ reloadItems / reloadSections / reloadData → dataSource.apply(snapshot) ● 差分に応じて自動でいい感じのアニメーション 14

Slide 15

Slide 15 text

©MIXI Cell Registration (iOS 14 +) ● セルの利用が型安全 ● 従来の方法のデメリット: 実行時クラッシュが発生しやすい ○ 事前にセルを登録していないと… ○ 表示するセルの取得時にtypoすると… ● 各々のプロジェクトでextension実装して解決していた ○ collectionView.register(CustomCell.self) ○ collectionView.dequeue(CustomCell.self, at: indexPath) ● 公式のAPIで実現できるようになった 15

Slide 16

Slide 16 text

©MIXI 解決していく ● すでにリリース済みのカレンダーUIを例に ● 仕様 ○ 現在のページがわかる ○ 表示したい月が増減したときにリロード ○ 現在のページが変化したときにリロード ○ 1画面内に6セル分入る 16

Slide 17

Slide 17 text

©MIXI UI & Cell作成 17 ● Storyboardで作成されていたため新規で作り直し

Slide 18

Slide 18 text

©MIXI Compositional Layoutsでレイアウト作成 18

Slide 19

Slide 19 text

©MIXI DataSource作成 19 ● セルに対応した型を用意 (Hashable必須) ○ ページの種類 ○ 現在のページかどうか

Slide 20

Slide 20 text

©MIXI DataSource作成 20

Slide 21

Slide 21 text

©MIXI CollectionViewの初期化 21 ● Layout 型と DataSource 型を個別に作っているため 初期化部分のコードがスッキリ

Slide 22

Slide 22 text

©MIXI UIの更新 22

Slide 23

Slide 23 text

©MIXI UIの更新 23 ● 現在のページを変更するときも reload メソッドを使う

Slide 24

Slide 24 text

©MIXI 成果 ● ほぼ同じ仕様のまま約45%までコードを削減 ○ +507 -1147 ● コードの見通しが良くなった ○ コード量が少なくなった ○ レイアウトの記述が宣言的 ○ データを更新するメソッドが1つに集約された ● 特定の条件下で発生していた画面崩れ解消 24

Slide 25

Slide 25 text

©MIXI リファクタリングに伴う仕様変更 ● スワイプでのページ遷移中のアニメーションを変更 ○ Diffable Data Sourceを使う場合 UIの状態とデータを一致させた方が実装しやすい ○ ピンクのバーではなくOffsetを動かす ● チームメンバーやPOに触っていただいた上で許容と判断 ○ リリース後、この変化をつぶやいている人は見つけられなかった 25 Before After

Slide 26

Slide 26 text

©MIXI まとめ

Slide 27

Slide 27 text

©MIXI まとめ ● iOS14以上で使えるUICollectionViewのAPIを活用して シンプルなコードにリファクタリングする方法を紹介 ○ コード量削減 & レイアウト崩れに強い ○ 現状の仕様を全て満たすのが難しい場合も存在する ● メディアを表示するCollectionViewも改善中 → ○ 今回紹介できなかったAPIも利用予定 NSDiffableDataSourceSectionSnapshot ● 今後も利用箇所を増やしていって シンプル & 画面崩れに強いUIを作っていきたい 27