如何通过代码触发UISwitch绑定的primaryAction?
我在一个SPM包中有一个UIViewController,其中包含一个UITableView,表格单元格为详情披露样式或带有UISwitch。我尝试编写单元测试,确认特定行的开关被切换时会调用预期动作。该动作由其他代码提供,单元格配置代码如下:
let toggle = UISwitch(frame: .zero, primaryAction: UIAction(handler: { action in guard let toggle = action.sender as? UISwitch else { return } toggleAction(toggle.isOn) })) cell.accessoryView = toggle
(其中toggleAction是传入VC初始化方法的多个参数之一)
我的测试可以找到目标行及对应的开关,也能通过.isOn修改其值,但无法触发绑定的动作。我知道.sendActions(for:)需要UIApplication环境,因此使用了相关解决方案(亲测对UIButton有效),尝试给UISwitch发送.touchUpInside、.valueChanged、.primaryActionTriggered等事件,但均未触发注册的动作。请问这是否可行?
可行,但得换个方式触发动作。你用primaryAction初始化开关时,这个动作并不会绑定到UISwitch的标准控件事件上,所以调用sendActions(for:)无效。给你几个实用方案:
直接调用UIAction的handler
既然开关是通过primaryAction创建的,你可以直接获取这个action并执行它,不需要依赖UIApplication环境,测试里用起来最直接:if let toggle = cell.accessoryView as? UISwitch, let action = toggle.primaryAction { action.perform(with: toggle, sender: toggle) }调整绑定动作的方式
如果你愿意修改单元格配置代码,可以放弃primaryAction,改用传统的addTarget绑定valueChanged事件:let toggle = UISwitch(frame: .zero) toggle.addTarget(self, action: #selector(handleToggleChange(_:)), for: .valueChanged) cell.accessoryView = toggle // 对应的处理方法 @objc func handleToggleChange(_ sender: UISwitch) { toggleAction(sender.isOn) }这种情况下,只要测试环境配置了UIApplication(比如初始化
UIApplication.shared),调用toggle.sendActions(for: .valueChanged)就能正常触发动作。用UI测试模拟真实交互
如果想完全贴近用户操作逻辑,可以改用XCTest的UI测试方案,通过XCUIApplication定位开关并模拟点击操作。注意这属于UI测试范畴,需要在SPM包中正确配置测试目标。
内容的提问来源于stack exchange,提问作者Chris

