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

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

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

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

Avatar for Koki Hirokawa

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 のメリットは大きいものの、実装・運用コストは少し高め