Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISlider addTarget and sendActions not working in UTs

When I run this code in a standard MVC project, all works fine: I can programmatically send actions to my 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)")
}

Now for some reason, when I want to simulate Slider behaviors in my UTs, it's not working. here is the code:

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)")
}

sliderTouch() is never called in the UT case and from my understanding, sendActions is not asnyc and should directly call the action methods.

So why am I getting this behavior, and how can I solve this?

Edit: I also need it to work for other UIKit controls such as UISwitch, UISegmentedControl, UIDatePicker etc...

like image 641
Guy Daher Avatar asked Dec 03 '22 22:12

Guy Daher


1 Answers

I had a problem similar to yours when testing classes contained in a Framework target.

Here is an excerpt from Apple's documentation:

When a control-specific event occurs, the control calls any associated action methods right away. Action methods are dispatched through the current UIApplication object, which finds an appropriate object to handle the message, following the responder chain if needed.

When testing a classes in a framework there is no UIApplication object and thus the events can not be dispatched.

You can add a Host Application in your test target settings. If you do not have a host application, you can just create an empty iOS app and use that.

Also see this post.

Update:

Here is how to set a Host Application:

Xcode Screenshot

If there is no Application in the dropdown, simply create a new Target and use the Application > Single View Application template.

You are done and your tests should now work. There are no additional steps.

like image 144
naglerrr Avatar answered Dec 20 '22 07:12

naglerrr