Slide 1

Slide 1 text

少年ジャンプ + iOS 曜日ランキングが 出来上がるまで id:tokizuoh 2024/09/19 はてなのモバイル開発大紹介! 1

Slide 2

Slide 2 text

2 話すこと

Slide 3

Slide 3 text

3 iOS アプリの 曜日ランキングを 作り上げた過程を紹介

Slide 4

Slide 4 text

4 UI の話をします

Slide 5

Slide 5 text

アジェンダ ● 曜日ランキングとは ● 最初の実装方針と出くわした課題 ● 課題に対するアプローチ 5

Slide 6

Slide 6 text

6 曜日ランキングとは

Slide 7

Slide 7 text

曜日ランキング ● ホーム画面の一番上に表示 ○ 曜日ごとにランキング形式で連載作品を 表示 ● 曜日間は横方向の無限スクロールで 移動 ● ベースは UIPageViewController ○ 大枠は SwiftUI ○ UIViewControllerRepresentable 7

Slide 8

Slide 8 text

8 最初の実装方針と 出くわした課題

Slide 9

Slide 9 text

9 背景と要件

Slide 10

Slide 10 text

● 曜日ランキングの表示位置はホーム画面の一番上 ○ 起動時にユーザーに必ず見てもらえる ○ 表示要素としての重要度が高い ● 作品を大切にしているため、ランキング表示 における省略表示は行わない ○ 曜日ごとに作品数が異なるため、表示数が異なる ○ 全ての曜日の連載作品を表示したい 背景 10

Slide 11

Slide 11 text

要件 11 ● 曜日ごとの作品数に応じて高さを変更 ● 横方向に無限スクロールして曜日を変更

Slide 12

Slide 12 text

12 やや複雑

Slide 13

Slide 13 text

13 SwiftUI でいけるのでは

Slide 14

Slide 14 text

要件 14 ● 曜日ごとの作品数に応じて高さを変更 ● 横方向に無限スクロールして曜日を変更

Slide 15

Slide 15 text

曜日ごとに高さが異なる 15

Slide 16

Slide 16 text

曜日ランキングの高さを曜日ごとに変更 ● 各曜日ごとの高さに応じて、曜日ランキング 自体の高さを変更する ○ SwiftUI ✅ ○ GeometryReader で曜日ごとの高さを取得し、 曜日変更毎に全体の高さとして適用 16

Slide 17

Slide 17 text

要件 17 ● 曜日ごとの作品数に応じて高さを変更 ● 横方向に無限スクロールして曜日を変更

Slide 18

Slide 18 text

要件 18 ● 曜日ごとの作品数に応じて高さを変更 ● 横方向に無限スクロールして曜日を変更

Slide 19

Slide 19 text

横方向に無限スクロールして曜日を変更 19 ● 横方向のスクロール ○ SwiftUI ✅ ○ ScrollView(.horizontal) ○ ページングを素朴に実装すると親要素の縦スクロールと競合 ■ 素朴: .gesture(_:including:) ■ → .simultaneousGesture(_:including:) と DragGesture(minimumDistance:) を使い、 縦横スクロールの競合をハンドリング

Slide 20

Slide 20 text

20 ホーム画面 は 縦方向も ScrollView

Slide 21

Slide 21 text

横方向に無限スクロールして曜日を変更 21 ● 無限スクロール ○ SwiftUI ✅ ○ .onChange(of:perform:) で選択中の曜日を 監視し、特定の曜日間の移動を特別扱い ■ 最初の曜日から左の曜日へ: 最後の曜日に移動 ■ 最後の曜日から右の曜日へ: 最初の曜日に移動

Slide 22

Slide 22 text

要件 22 ● 曜日ごとの作品数に応じて高さを変更 ● 横方向に無限スクロールして曜日を変更

Slide 23

Slide 23 text

23 実装できたが...

Slide 24

Slide 24 text

24 表示が崩れる

Slide 25

Slide 25 text

SwiftUI 版は背景がズレる 25 25

Slide 26

Slide 26 text

SwiftUI 版の課題 26 ● 表示が崩れる ● 加えて、操作感が良くない ○ 横スクロールの手触りが悪く、反応が悪い ■ なめらかさを感じない ○ 横スクロールをしたつもりが親要素の縦スクロールが 優先される時があった ■ 公開されている値で調整しても満足感は得られなかった

Slide 27

Slide 27 text

27 課題に対する アプローチ

Slide 28

Slide 28 text

課題 28 ● SwiftUI ではパフォーマンスや操作感を 満たせない ○ 原因が分からなかった ○ → UIKit をベースに方向転換

Slide 29

Slide 29 text

UIKit でどのように作るか (1/2) 29 ● UIKit といってもやり方は色々ある ○ UIScrollView ○ UICollectionView ○ UIPageViewController

Slide 30

Slide 30 text

UIKit でどのように作るか (2/2) ● 各曜日間のスクロールはページング ○ 各曜日ごとにピッタリ止まってほしい ○ → UIPageViewController を使ってみる 30

Slide 31

Slide 31 text

31 操作感 パフォーマンス OK

Slide 32

Slide 32 text

UIKit 版は背景がズレない 32 32

Slide 33

Slide 33 text

操作感・パフォーマンス ● 動作が遅くない ○ なめらかに曜日間の移動ができた ● 意図した通りに縦横スクロールができる ○ 標準のAPIを使うことで操作感が自然となった 33

Slide 34

Slide 34 text

要件は満たせたか? (1/2) 34 ● 曜日ごとの作品数に応じて高さを変更 ○ → SwiftUI で作った時と同じ処理 ■ 各曜日は SwiftUI.View から変更無し ■ > GeometryReader で曜日ごとの高さを取得し、 曜日変更毎に全体の高さとして適用 ○ 細かな不具合の対応も複数行った ■ スクロール中に高さを変更するとパフォーマンスが落ちる等

Slide 35

Slide 35 text

要件は満たせたか? (2/2) 35 ● 横方向に無限スクロールして曜日を変更 ○ → UIPageViewControllerDelegate

Slide 36

Slide 36 text

最終的な構成 ● ホーム画面 SwiftUI.ScrollView ○ 曜日ランキング SwiftUI.View ■ ヘッダー SwiftUI.View ■ 全曜日 UIViewControllerRepresentable ● UIPageViewController ○ 各曜日 UIHostingController ■ SwiftUI.View 36

Slide 37

Slide 37 text

まとめ ● 曜日ランキングとは ○ → 曜日ごとにランキング形式で連載作品を表示 ● 最初の実装方針と出くわした課題 ○ → SwiftUI だけで作るとパフォーマンスが悪かった ● 課題に対するアプローチ ○ → UIPageViewController を使うことで課題を解消できた 37