Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftUI移行のためのインプレッショントラッキング基盤の構築

 SwiftUI移行のためのインプレッショントラッキング基盤の構築

CA.swift #22 〜Swiftの進化を活かした技術基盤への挑戦〜 にて登壇。
https://cyberagent.connpass.com/event/342952/

Koki Hirokawa

March 03, 2025
Tweet

More Decks by Koki Hirokawa

Other Decks in Programming

Transcript

  1. AbemaTV, Inc. All Rights Reserved
 AbemaTV, Inc. All Rights Reserved


    1 SwiftUI 移行のための インプレッション トラッキング基盤の構築 2025 March 3rd Koki Hirokawa
  2. AbemaTV, Inc. All Rights Reserved
 SwiftUI への移行 3 SwiftUI •

    新規実装は SwiftUI 主体 • UIKit はスポット利用 UIKit
  3. AbemaTV, Inc. All Rights Reserved
 移行における課題 4 • キャッチアップ •

    iOS 15.0 までのサポート • インプレッショントラッキングの仕組み
  4. AbemaTV, Inc. All Rights Reserved
 移行における課題 5 • キャッチアップ •

    iOS 15.0 までのサポート • インプレッショントラッキング の仕組み ✔ ✔ ✔ ✔
  5. AbemaTV, Inc. All Rights Reserved
 目次 6 • 自己紹介 •

    インプレッショントラッキングとは • SwiftUI での基盤構築 • 工夫した点 • まとめ
  6. AbemaTV, Inc. All Rights Reserved
 インプレッションログ 11 ✔ ✔ ✔

    ✔ .onAppear { sendImpressionLog(id: “mylist-\(id)”) } • シンプルな実装
  7. AbemaTV, Inc. All Rights Reserved
 インプレッションログ 12 ✔ ✔ ✔

    ✔ .onAppear { sendImpressionLog(id: “mylist-\(id)”) } • 「見た」の定義はもう少し複雑 ❌
  8. AbemaTV, Inc. All Rights Reserved
 インプレッションログ 13 ✔ ✔ ✔

    • 例) 要素の80%以上の領域が画面内に2秒以上 表示されたことを、ユーザが「見た」と定義する ✔
  9. AbemaTV, Inc. All Rights Reserved
 前提 15 • ABEMA では多くの画面がスクロール可能

    • UIKit では TableView や CollectionView で表示するコンテンツのインプレッション をトラッキングするための基盤を用意
  10. AbemaTV, Inc. All Rights Reserved
 利用イメージ 17 @StateObject var controller

    = ImpressionTrackingController( configuration: .init( minimumAreaRatio: 0.8, minimumDuration: 2 ) )
  11. AbemaTV, Inc. All Rights Reserved
 利用イメージ 18 TrackableScrollView(showsIndicator: false) {

    LazyVStack { ForEach(fruits) { fruit in FruitView(fruit) .trackable(id: fruit.id) { sendImpressionLog() } } } } .environment(\.trackingController, controller)
  12. AbemaTV, Inc. All Rights Reserved
 Trackable ScrollView - RootViewFrame のキャッシュ

    19 ImpressionTrackingController Trackable ScrollView .onChange( geometry.frame(in: .global) ) { frame in controller.setRootViewFrame(frame) }
  13. AbemaTV, Inc. All Rights Reserved
 Trackable ScrollView - スクロールの検知 20

    ImpressionTrackingController Trackable ScrollView .onChange( geometry.frame(in: .named(space)).origin ) { origin in if origin != prevOrigin { controller.sendScrollEvent() } }
  14. AbemaTV, Inc. All Rights Reserved
 21 Trackable View - インプレッションのロジック

    Trackable View .onReceive(controller.didScroll) { let visibility = … if 0.8 <= visibility { // タイマーを設定 () } else { // タイマーを停止 () } } ImpressionTrackingController
  15. AbemaTV, Inc. All Rights Reserved
 22 Trackable View - 条件を満たした場合

    Trackable View .onReceive(controller.didTrack) { // ログ送信 } ImpressionTrackingController
  16. AbemaTV, Inc. All Rights Reserved
 デバッグ画面 26 • 必ず実機でも確認する ◦

    シミュレータと実機で挙動が変わることがあるため注意 • OS Major Version も網羅しておくと安心
  17. AbemaTV, Inc. All Rights Reserved
 UI Test 28 • 想像以上に実行時間が長い

    ◦ 表示内容の検証をしている間に指定した インプレッションの秒数を超える
  18. AbemaTV, Inc. All Rights Reserved
 UI Test 29 • 想像以上に実行時間が長い

    ◦ 表示内容の検証をしている間に指定した インプレッションの秒数を超える ▪ 1秒から3秒に変更
  19. AbemaTV, Inc. All Rights Reserved
 UI Test 31 • ボタンをタップできずテストが失敗

    ◦ タップ可能になるまで待機 try await app.buttons[“Scroll to Bottom”] .abema.tapOnHittable()
  20. AbemaTV, Inc. All Rights Reserved
 UI Test 33 • 固定量のスクロールができない

    ◦ 慣性スクロールが働く ◦ デバッグ画面では最下部までスクロールするためのボタンを追加
  21. AbemaTV, Inc. All Rights Reserved
 デバッグ機能 34 • Environment Variables

    • トラッキング対象にオーバーレイ を配置し、視覚的にデバッグ
  22. AbemaTV, Inc. All Rights Reserved
 まとめ 36 • SwiftUI 主体の実装へ移行するにあたって、インプレッションログを送信するための基

    盤を構築 • TrackableScrollView や trackable modifier を用意することで、実装コストを抑えてイ ンプレッションログの送信ができるように • UI Test のメリットは大きいものの、実装・運用コストは少し高め