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

UI Tests中如何实现元素按下、截图再释放的操作?

解决UITest中按压元素时截图的问题

你的问题出在press(forDuration:)的执行逻辑上——这个方法是先完成整个按压+释放的动作后,才会执行后续的代码,所以你现在的截图是在元素被松开后才触发的,自然看不到按压状态下的界面。

要实现「按住元素 → 截图 → 释放」的流程,我们需要把按压操作和截图操作异步拆分,确保截图发生在按压持续的过程中。以下是具体的实现方案:

步骤1:优化元素定位(可选但强烈推荐)

首先,尽量避免用多层嵌套的children(matching:)来定位元素,这种写法非常脆弱,UI层级稍有变动就会失效。建议在App的代码中给目标元素设置可访问性标识符:

// App端代码(比如UIViewController里)
yourTargetElement.accessibilityIdentifier = "EffectsPressTarget"

然后在UITest中直接通过标识符获取元素:

let targetElement = app.otherElements["EffectsPressTarget"]

步骤2:实现按压中截图的逻辑

核心思路是异步启动按压操作,等按压生效后立刻截图,最后等待按压完成释放元素:

// 获取目标元素(如果用了accessibilityIdentifier就用上面的写法)
let targetElement = app.children(matching: .window)
    .element(boundBy: 0)
    .children(matching: .other)
    .element
    .children(matching: .other)
    .element(boundBy: 1)
    .children(matching: .other)
    .element(boundBy: 3)

// 获取元素的中心坐标(确保按压位置准确)
let elementCoordinate = targetElement.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))

// 异步启动按压,设置足够长的持续时间(比如2秒,给截图留足时间)
DispatchQueue.global().async {
    elementCoordinate.press(forDuration: 2.0)
}

// 短暂等待(0.2秒左右),确保按压已经触发并显示出按压状态的UI
Thread.sleep(forTimeInterval: 0.2)

// 执行截图,这时候元素处于被按住的状态
snapshot("EffectsScreenshot")

// 等待按压操作完成(剩下的1.8秒),元素会自动释放
Thread.sleep(forTimeInterval: 1.8)

为什么这个方案可行?

  • DispatchQueue.global().async把按压操作放到后台队列执行,不会阻塞主线程的截图逻辑
  • 短暂的Thread.sleep是为了确保系统已经处理了按压事件,界面显示出按压状态(比如高亮、弹出菜单等)
  • 最后等待按压完成,元素会自动释放,符合你想要的完整流程

如果你觉得Thread.sleep不够优雅,也可以用XCTWaiter配合预期条件来代替,比如等待元素的按压状态出现,但对于简单的场景,Thread.sleep已经足够好用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:36:46