当我在标准MVC项目中运行此代码时,一切正常:我可以通过编程方式将动作发送到我的UISlider。
override func viewDidLoad() {
super.viewDidLoad()
slider = UISlider(frame: CGRect(x: 100, y: 100, width: 200, height: 50))
slider.minimumValue = 1
slider.maximumValue = 100
slider.addTarget(self, action: #selector(sliderTouch), for: .touchUpInside)
slider.sendActions(for: .touchUpInside)
}
func sliderTouch(sender: UISlider) {
print("value: \(sender.value)")
}
现在由于某种原因,当我想在我的UT中模拟Slider行为时,它不起作用。这是代码:
func testSlider() {
let slider = UISlider(frame: CGRect(x: 100, y: 100, width: 200, height: 50))
slider.minimumValue = 1
slider.maximumValue = 100
slider.addTarget(self, action: #selector(sliderTouch), for: .touchUpInside)
slider.sendActions(for: .touchUpInside)
}
func sliderTouch(sender: UISlider) {
print("value: \(sender.value)")
}
在UT情况下永远不会调用 sliderTouch()
,根据我的理解,sendActions不是asnyc
,应直接调用操作方法。
那么为什么我会得到这种行为,我该如何解决这个问题?
修改:我还需要它可以用于其他UIKit控件,例如UISwitch
,UISegmentedControl
,UIDatePicker
等...
答案 0 :(得分:5)
在测试Framework目标中包含的类时,我遇到了与您类似的问题。
当发生控件特定事件时,控件立即调用任何关联的操作方法。通过当前的UIApplication对象调度Action方法,该对象根据需要在响应者链之后找到处理消息的适当对象。
在框架中测试类时,没有UIApplication
对象,因此无法调度事件。
您可以在测试目标设置中添加主机应用程序。如果您没有主机应用程序,则可以创建一个空iOS应用程序并使用它。
另见this post。
<强>更新强>
以下是如何设置主机应用程序:
如果下拉列表中没有应用程序,只需创建一个新目标并使用应用程序&gt; 单一视图应用模板。
你已经完成了,你的测试现在应该可行了。没有其他步骤。
答案 1 :(得分:1)
或尝试子类化:
class TouchSlider: UISlider {
var touchUpInsideHandler: ((TouchSlider) -> Void)?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touchUpInsideHandler?(self)
guard let touch = touches.first,
let imageWidth = currentThumbImage?.size.width else {
super.touchesBegan(touches, with: event)
return
}
let location = touch.location(in: self)
let newValue: Float = minimumValue + (maximumValue - minimumValue) * Float((location.x - imageWidth / 2.0) / (bounds.width - imageWidth))
setValue(newValue, animated: true)
super.touchesBegan(touches, with: event)
}
}
使用touchUpInsideHandler
管理外面的动画。