I just noticed that setting a UISwitch's isOn
in its IBAction causes the IBAction to be called again. So the following code:
class ViewController: UIViewController {
var count = 0
@IBOutlet weak var mySwitch: UISwitch!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
mySwitch.isOn = false
}
@IBAction func buttonTapped(_ sender: UIButton) {
mySwitch.isOn = !mySwitch.isOn
}
@IBAction func switchChanged(_ sender: UISwitch) {
print("\(count) pre: \(mySwitch.isOn)")
mySwitch.isOn = !mySwitch.isOn
print("\(count) post: \(mySwitch.isOn)")
count += 1
}
}
prints the following when the switch is turned on one time:
0 pre: true
0 post: false
1 pre: false
1 post: true
- switch is turned off in
viewDidLoad
- switch is turned on by the user
- switch is on now when
switchChanged
(IBAction) is called 0 pre: true
is printed- switch is turned off programmatically in
switchChanged
0 post: false
is printedswitchChanged
is called again by the system- switch is off now in
switchChanged
, and1 pre: false
is called - switch is turned on programmatically
1 post: true
is printed
Why is the IBAction called by the system a second time? How does one get around this, say, for example, when wanting to negate the user's action based upon some internal state? I feel like I am missing something embarrassingly obvious, but I'm pretty sure similar code used to work. Is this an iOS bug? It's being run on an iOS 10.2 iPhone 5s simulator, Xcode Version 8.2.1 (8C1002)
It's interesting to note that when the button tied to buttonTapped
is tapped (calling that same method), the switch's IBAction is not called.