我刚注意到在其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
viewDidLoad
switchChanged
(IBAction)0 pre: true
已打印switchChanged
0 post: false
已打印switchChanged
switchChanged
,1 pre: false
被称为1 post: true
已打印为什么系统第二次调用IBAction?例如,当想要根据某些内部状态否定用户的行为时,如何解决这个问题呢?我觉得我错过了一些令人尴尬的东西,但我很确定类似的代码曾经工作过。这是iOS错误吗?它运行在iOS 10.2 iPhone 5s模拟器上,Xcode版本8.2.1(8C1002)
有趣的是,当点击绑定到buttonTapped
的按钮(调用相同的方法)时,不会调用开关的IBAction。
答案 0 :(得分:0)
您的IBAction可能与valueChanged
挂钩,这并不表示特定的触摸事件,正如它所说的那样,值已被更改。
我建议设置一个名为var didOverrideSwitchValue = false
的变量,在设置新的开关值之前将其设置为true
,然后在调用该函数时,检查该变量。如果设置为true
,则将其设置为false
并返回。
或者,如果您希望仅在打开时取消新设置,那么您可以if (switch.isOn)
,然后如果是,那么您可以根据需要关闭它,如果需要的话。
答案 1 :(得分:0)
我一直在同一个问题作斗争,并找到了解决方法...
在切换处理程序中检查发送方的“ selected”属性。我发现第一次是正确的,第二次是false,因此您可以判断用户操作是否真的在调用您。
我猜是第二次触发该事件的原因不是开关本身,还是该属性在处理第一个事件后被清除。也许UIKit大师可以发出声音。
-setOn:animated的UISwitch文档:说
将开关设置到任一位置都不会导致发送操作消息。
似乎很清楚。感觉像操作系统错误。
无论如何,这似乎是可行的,但它使我感到不安,因为我不完全理解为什么问题首先存在,也无法完全解决问题的原因,并且我担心在将来的操作系统更新中它们可能会改变。
更新
这在我的小型测试应用程序中能正常工作,但在我的真实应用程序中却不能,在真实的应用程序中,它具有更复杂的UI层次结构(带有导航栏,标签等)。这只会加剧我对此解决方案的不安。