3

In previous versions of iOS, IBActions were only triggered in response to user action. Now, it seems that they are also triggered by interactions through code on the same thread as the user interaction... I probably didn't word it that well, but here is an example:

@IBAction func switchToggled(_ sender: UISwitch) {
     sender.setOn(!sender.isOn, animated: true)
}

Neato. There's our element. The behavior that I would expect in iOS 9 and below is:

  1. User taps switch
  2. Animation begins
  3. IBAction is hit, and animation reverses

However, in iOS 10, step 3 is revised to

  1. IBAction is hit, setOn is called within action, then IBAction is hit again

For UISwitch, the IBAction only seems to get called twice.

My guess is that since the second setOn matches the direction of the current animation, it doesn't trigger another valueChanged event for the switch, therefore not triggering a 3rd IBAction.

Another observation is that if the setOn method is called in a completion block or something, it does not trigger the IBAction. For example:

someViewController.present(someOtherController,
                           animated: true,
                           completion: { theSwitch.setOn(true) })

This does not trigger an IBAction, regardless of the animation state of the UISwitch

Was there a change in iOS 10 that I was not privy to? Or is my assumption that IBActions are exclusively meant for explicit user interactions incorrect? (Yes, I know you can manually send events to UI elements to make them do things, but this isn't what I'm talking about)

Cheers!

Joe
  • 8,868
  • 8
  • 37
  • 59
ciauri
  • 513
  • 5
  • 13
  • I tested this and it looks like a bug to me. According to the document for both iOS9 and iOS10 `setOn` is not supposed to send action messages but in this particular situation it seems that it is sending an action message. – Swifty Oct 08 '16 at 22:49

0 Answers0