You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS UI测试:如何访问NavigationStack中的搜索栏?

解决NavigationStack内嵌searchable搜索栏的UI测试访问问题

问题根源

  1. 标识符绑定错误:你将accessibilityIdentifier附加到了NavigationStack容器视图上,而非searchable生成的搜索输入框本身。app.searchFields只会匹配类型为搜索输入框的元素,NavigationStack不属于这类元素,因此无法找到目标。
  2. 搜索栏默认隐藏:searchable修饰符生成的搜索栏默认处于折叠隐藏状态,直接查找会因元素未显示而失败。

修正方案

1. 调整业务代码,给搜索栏正确设置标识符

将accessibilityIdentifier直接绑定到搜索输入框上,而非容器视图,有两种实现方式:

方式一:自定义搜索栏视图

通过searchable的闭包自定义搜索输入框,并设置标识符:

var body: some View {
    NavigationStack {
        List {
            // 业务列表元素
        }
    }
    .searchable(text: $searchText) {
        TextField("搜索", text: $searchText)
            .accessibilityIdentifier("SearchField")
    }
}

方式二:给默认搜索栏绑定标识符

如果使用系统默认搜索栏,可调整可访问性层级确保标识符关联到搜索栏:

var body: some View {
    NavigationStack {
        List {
            // 业务列表元素
        }
    }
    .searchable(text: $searchText)
    .accessibilityElement(children: .contain)
    .accessibilityIdentifier("SearchField")
}

2. 修正UI测试代码,先触发搜索栏显示

默认状态下搜索栏隐藏,需先触发显示再进行操作:

override func setUpWithError() throws {
    continueAfterFailure = false

    let app = XCUIApplication()
    app.launch()

    // 触发搜索栏显示:点击导航栏上的搜索折叠按钮
    app.navigationBars.buttons["Search"].tap()
    // 若搜索栏通过下拉列表触发,可替换为:
    // app.tables.firstMatch.swipeDown()

    // 验证搜索栏存在
    let searchField = app.searchFields["SearchField"]
    XCTAssertTrue(searchField.exists, "搜索栏应该存在")

    // 输入搜索文本
    searchField.tap()
    searchField.typeText("测试搜索内容")

    // 执行搜索:点击键盘上的搜索按钮
    app.keyboards.buttons["Search"].tap()
    // 或直接输入回车触发:
    // searchField.typeText("\r")
}

备选方案:无需修改业务代码的查找方式

如果无法调整业务代码,可通过元素层级直接定位搜索栏:

// 从导航栏中查找搜索输入框
let searchField = app.navigationBars.children(matching: .searchField).firstMatch
XCTAssertTrue(searchField.exists)

内容的提问来源于stack exchange,提问作者victorydub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 07:03:20