LoginSignup
3
1

More than 3 years have passed since last update.

SwiftUIのTabBarButtonにAccessibilityIdentifierを設定する

Posted at

SwiftUIのIntegrationTestを行いたい場合、新しいフレームワークである都合から実機を用いたテストを行うのが良いです。
(Preview・シミュレーターだと実機で発生するような不具合に気がつくことが出来ない、そして、そういったケースがやたらと多い…)

このテストを自動化したい場合、利用出来るテストツールにはAppiumが挙げられるかと思います。

SwiftUIでTabViewを利用する場合、各TabBarItem(TabBarButton)にAccessibilityIdentifierを設定する方法が提供されおらず、Appium側からTabの切り替え操作を行うことができません。
(Appiumではユニークな要素取得のためにAccessibilityIdentifierを参照します)

UITabBarControllerにアクセスする

SwiftUIではUIKitの要素に触ることは出来ませんので、SwiftUI-Introspectというライブラリを利用します。
これを利用することで、以下のようにUITabBarControllerへの参照を取得出来るようになります。

import SwiftUI
import Introspect

struct ContentView: View {
    var body: some View {
        TabView {
            Text("Tab1").tabItem {
                Label("tab1", systemImage: "circle")
            }
            Text("Tab2").tabItem {
                Label("tab2", systemImage: "square")
            }
        }
        .introspectTabBarController { tabBarController in
            print(tabBarController)
        }
    }
}

UITabBarButtonにAccessibilityIdentifierを設定する

TabViewにあるボタンはUITabBarButtonというViewです。
(TabBarItemではありません!)
UITabBarButtonはUIKitでは公開されていないViewなのでこの型名を指定してUITabBarButtonを取得することは出来ないのですが、
幸いにもUIControlを継承しているViewなのでキャストを通して参照を取得することが出来ます。

let tabButtons = tabBarController.tabBar.subviews.compactMap { $0 as? UIControl }

取得したUIControlの参照は左から並ぶTabBarButtonとなるので、配列のIndexを見ながら各ボタンに適当なIdentifierを設定していけばOKです。

tabButtons.enumerated().forEach { (index, tabButton) in
    switch index {
    case 0:
        tabButton.accessibilityIdentifier = "tab1"
    case 1:
        tabButton.accessibilityIdentifier = "tab2"
    default:
        break
    }
}

将来的に言語・フレームワークのアップデートで動作しなくなる可能性がある方法です。
将来的にはこのような方法を採用しなくても、AccessibilityIdentifierを設定するより良い方法が提供されるようになることを期待したいですね。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1