如何修复Xcode14.1+ UI测试中无效点击点引发的滚动可见失败错误?
问题描述
本地及CI环境的Xcode UI测试原本运行正常,升级至Xcode 14.1(Xcode 14.2同样存在问题)后,部分涉及非UITableView滚动视图的按钮点击场景出现非必现失败:
- 测试始终能定位到目标按钮,
exists属性保持为true - 失败时日志显示按钮计算的点击点为
{-1, -1}(无效坐标),但按钮实际拥有有效布局坐标(如示例中的{{338.0, 51.0}, {36.0, 36.0}}) - 即便按钮需要滚动到视野内,tap操作能触发滚动动作,但点击点无效时无法完成点击
失败日志示例
t = 2369.32s Check for interrupting elements affecting "Close" Button
t = 2369.38s Synthesize event
t = 2369.40s Scroll element to visible
t = 2369.40s Find the "Close" Button
t = 2369.43s Computed hit point {-1, -1} after scrolling to visible
t = 2369.43s Failed: Failed to scroll to visible (by AX action) Button, {{338.0, 51.0}, {36.0, 36.0}}, label: 'Close', error: Error kAXErrorCannotComplete performing AXAction kAXScrollToVisibleAction on element AX element pid: 28238, elementOrHash.elementID: 4624960864.301
已尝试过提前添加swipeUp/swipeDown、waitForExistence等操作,但无法稳定解决问题。
核心判断
这大概率是Xcode 14.1+的特定bug——该版本对滚动视图元素的点击点计算逻辑、无障碍动作执行时机存在异常,Xcode 14.0及更早版本无此问题,触发条件可能和滚动视图布局、元素无障碍属性的组合有关。
可尝试的修复方案
1. 手动计算点击坐标触发点击
既然按钮的frame是有效的,直接取frame中心坐标手动生成点击动作,替代默认的tap()方法:
let closeButton = app.buttons["Close"] let buttonFrame = closeButton.frame // 基于应用根坐标生成按钮中心坐标 let centerCoordinate = app.coordinate(withNormalizedOffset: .zero) .withOffset(CGVector(dx: buttonFrame.midX, dy: buttonFrame.midY)) centerCoordinate.tap()
2. 等待按钮变为可点击状态后再操作
Xcode 14.1+可能在滚动完成前就尝试计算点击点,添加对isHittable属性的等待:
let closeButton = app.buttons["Close"] let isHittablePredicate = NSPredicate(format: "isHittable == true") expectation(for: isHittablePredicate, evaluatedWith: closeButton, handler: nil) waitForExpectations(timeout: 5, handler: nil) closeButton.tap()
3. 禁用自动滚动,手动控制滚动时机
关闭XCUIElement的自动滚动行为,手动滚动到按钮区域后再点击:
let closeButton = app.buttons["Close"] // 手动滚动到按钮所在方向(示例为向上滚动) app.scrollViews.firstMatch.swipeUp() // 等待按钮加载完成 closeButton.waitForExistence(timeout: 5) closeButton.tap()
4. 检查并修复无障碍属性
确保滚动视图和按钮的accessibilityIdentifier设置正确,避免按钮的无障碍区域被滚动视图遮挡——Xcode 14.1+对无障碍元素的优先级计算逻辑有调整,属性冲突可能导致点击点计算异常。
5. 临时降级Xcode版本(应急方案)
如果上述方法均无效,且项目允许,可以暂时降级到Xcode 14.0,恢复UI测试的稳定性,等待苹果后续版本修复该bug。
内容的提问来源于stack exchange,提问作者shim

