设置UISwitch是以编程方式从IBAction再次调用IBAction

时间:2017-03-03 22:17:47

标签: ios

我刚注意到在其IBAction中设置UISwitch的isOn会导致再次调用IBAction。所以下面的代码:

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
    }
}
当开关打开一次时,

打印以下内容:

0 pre: true
0 post: false
1 pre: false
1 post: true
  1. viewDidLoad
  2. 中关闭了开关
  3. 用户打开了开关
  4. 在调用switchChanged(IBAction)
  5. 时启用此开关
  6. 0 pre: true已打印
  7. switchChanged
  8. 中以编程方式关闭了开关
  9. 0 post: false已打印
  10. 系统再次调用
  11. switchChanged
  12. 现在关闭switchChanged1 pre: false被称为
  13. 以编程方式启用开关
  14. 1 post: true已打印
  15. 为什么系统第二次调用IBAction?例如,当想要根据某些内部状态否定用户的行为时,如何解决这个问题呢?我觉得我错过了一些令人尴尬的东西,但我很确定类似的代码曾经工作过。这是iOS错误吗?它运行在iOS 10.2 iPhone 5s模拟器上,Xcode版本8.2.1(8C1002)

    有趣的是,当点击绑定到buttonTapped的按钮(调用相同的方法)时,不会调用开关的IBAction。

2 个答案:

答案 0 :(得分:0)

您的IBAction可能与valueChanged挂钩,这并不表示特定的触摸事件,正如它所说的那样,值已被更改。

我建议设置一个名为var didOverrideSwitchValue = false的变量,在设置新的开关值之前将其设置为true,然后在调用该函数时,检查该变量。如果设置为true,则将其设置为false并返回。

或者,如果您希望仅在打开时取消新设置,那么您可以if (switch.isOn),然后如果是,那么您可以根据需要关闭它,如果需要的话。

答案 1 :(得分:0)

我一直在同一个问题作斗争,并找到了解决方法...

在切换处理程序中检查发送方的“ selected”属性。我发现第一次是正确的,第二次是false,因此您可以判断用户操作是否真的在调用您。

我猜是第二次触发该事件的原因不是开关本身,还是该属性在处理第一个事件后被清除。也许UIKit大师可以发出声音。

-setOn:animated的UISwitch文档:说

  

将开关设置到任一位置都不会导致发送操作消息。

似乎很清楚。感觉像操作系统错误。

无论如何,这似乎是可行的,但它使我感到不安,因为我不完全理解为什么问题首先存在,也无法完全解决问题的原因,并且我担心在将来的操作系统更新中它们可能会改变。

更新

这在我的小型测试应用程序中能正常工作,但在我的真实应用程序中却不能,在真实的应用程序中,它具有更复杂的UI层次结构(带有导航栏,标签等)。这只会加剧我对此解决方案的不安。

相关问题