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

如何在XCTest中提取SwiftUI Menu Picker的真实选项?

解决SwiftUI Menu Picker在XCTest中获取多余选项的问题

你遇到的问题是因为使用.menu样式的Picker时,点击弹出菜单后,原来的Picker按钮(显示"Choose an option, Option 1")仍然停留在界面上,而你遍历的是全局的app.buttons,所以把这个按钮也包含进了结果里。下面是几种可行的解决办法:

方法1:直接定位菜单内的选项(最推荐)

SwiftUI的MenuPicker弹出的菜单会被归类到XCUIApplication().menus层级下,直接获取菜单容器内的按钮,就能只拿到真正的选项:

修改测试代码中获取选项的部分:

// Tap the picker to bring up the menu.
picker.tap()

// 定位弹出的菜单,只取菜单内的按钮
let menu = app.menus.firstMatch
let pickerItems = menu.buttons.allElementsBoundByIndex

// Extract menu choices.
var menuChoices: [String] = []
for item in pickerItems {
    menuChoices.append(item.label)
}

这样收集到的menuChoices就只会是["Option 1", "Option 2", "Option 3", "Option 4"],不会包含额外的条目。

方法2:过滤不符合预期的条目

如果不想依赖菜单层级,也可以直接过滤掉包含Picker标题的条目,或者只保留预期的选项:

首先在测试代码里定义和应用一致的预期选项数组:

let expectedOptions = ["Option 1", "Option 2", "Option 3", "Option 4"]

然后在收集选项时过滤:

// Extract menu choices and filter
let menuChoices = pickerItems
    .map(\.label)
    .filter { expectedOptions.contains($0) }

或者直接过滤掉包含Picker标题的条目:

let menuChoices = pickerItems
    .map(\.label)
    .filter { !$0.contains("Choose an option") }

方法3:通过辅助标识精准定位选项

更可靠的方式是给每个Picker选项设置唯一的辅助标识,避免依赖文本内容:

修改SwiftUI应用代码中的Picker选项部分:

ForEach(options, id: \.self) { option in
    Text(option)
        .accessibilityIdentifier("picker-option-\(option)")
}

然后在测试代码中通过标识匹配获取选项:

// Tap the picker to bring up the menu.
picker.tap()

// 匹配所有以"picker-option-"开头的按钮
let pickerItems = app.buttons.matching(
    identifier: NSPredicate(format: "BEGINSWITH %@", "picker-option-")
).allElementsBoundByIndex

// 提取选项文本
let menuChoices = pickerItems.map { $0.label }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 22:39:52