升级iOS15/Xcode13后addUIInterruptionMonitor无法关闭弹窗如何解决
问题原因
iOS 15 + Xcode 13 对UI测试的弹窗拦截逻辑做了3个核心变更,是原有代码失效的根因:
addUIInterruptionMonitor的回调触发优先级降低,系统弹窗出现后会优先走XCTest内置处理逻辑,自定义拦截器不会第一时间被调用- 弹窗按钮索引规则调整,原有靠
element(boundBy: 0)取按钮的逻辑不再适配,部分权限弹窗的按钮顺序被系统修改,甚至部分场景下拦截器拿到的alert元素本身为空 - 原有配套的
app.tap()唤醒拦截器的逻辑失效,iOS15下该空点击大概率不会触发拦截器执行
修复方案
1. 调整拦截器实现,用按钮文字匹配替代索引定位
硬编码索引的稳定性极低,替换为按钮文字匹配的方式,同时先校验alert元素有效性:
addUIInterruptionMonitor(withDescription: "System Dialog") { alert -> Bool in guard alert.exists else { return false } // 可根据业务需要补充需要匹配的按钮文字 let targetButtonTitles = ["不允许", "Don't Allow", "确定", "OK", "取消", "Cancel"] for title in targetButtonTitles { let targetBtn = alert.buttons[title] if targetBtn.exists && targetBtn.isHittable { targetBtn.tap() return true } } // 未匹配到目标按钮返回false,交给后续拦截器处理 return false }
2. 替换空点击触发逻辑,增加等待+多次尝试
iOS15下单次空点击触发拦截的概率很低,调整为等待弹窗加载完成后多次触发:
// 等待2秒确保弹窗完全弹出 Thread.sleep(forTimeInterval: 2) // 多次尝试触发拦截器 for _ in 0..<2 { app.tap() Thread.sleep(forTimeInterval: 0.5) }
3. 极端场景降级方案:直接访问SpringBoard系统进程处理弹窗
如果自定义拦截器完全无法触发,可以直接获取系统进程的弹窗元素,优先级高于XCTest内置拦截逻辑:
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let systemAlert = springboard.alerts.firstMatch if systemAlert.exists { let targetBtn = systemAlert.buttons["不允许"] if targetBtn.exists { targetBtn.tap() } }
内容的提问来源于stack exchange,提问作者vulkandev
相关产品推荐
相关产品推荐

