iOS7 UISwitch它的Event ValueChanged:连续调用这个Bug还是什么..?

时间:2013-10-28 06:22:49

标签: ios iphone ios7 xcode5 uiswitch

修改

现已修复
不要做任何调整来解决它。

EDIT2

显然,在iOS 8.0和8.1中再次出现同样的问题

EDIT3

现已修复
不要做任何调整来解决它。


嗨今天我在UISwitch's活动ValueChanged:中看到,当我更改为continuouslyOnOff至开启时,请致电Off我的手指仍然在右侧和左侧移动。我使用NSLog更加清晰地看了GIF图像。

enter image description here

我的价值改变方法是:

- (IBAction)changeSwitch:(id)sender{

    if([sender isOn]){
        NSLog(@"Switch is ON");
    } else{
        NSLog(@"Switch is OFF");
    }

}

iOS6相同的Switch代码工作正常,我们期待:

enter image description here

所以任何人都可以建议我只打电话或关闭一次状态。或者这是一个错误或什么..?

更新

这是我的演示:

programmatic Add UISwitch

from XIB adding UISwitch

12 个答案:

答案 0 :(得分:44)

请参阅以下代码:

-(void)viewDidLoad
{
    [super viewDidLoad];    
    UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(130, 235, 0, 0)];    
    [mySwitch addTarget:self action:@selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:mySwitch];
}

- (void)changeSwitch:(id)sender{
    if([sender isOn]){
        NSLog(@"Switch is ON");
    } else{
        NSLog(@"Switch is OFF");
    }
}

答案 1 :(得分:12)

这里有同样的错误。我想我找到了一个简单的解决方法。我们只需要使用一个新的BOOL来存储UISwitch的先前状态和IBAction中的if语句(触发值已更改)以检查交换机的值是否实际改变。

previousValue = FALSE;

[...]

-(IBAction)mySwitchIBAction {
    if(mySwitch.on == previousValue)
        return;
    // resetting the new switch value to the flag
    previousValue = mySwitch.on;
 }

没有更奇怪的行为。希望它有所帮助。

答案 2 :(得分:12)

您可以使用UISwitch的{​​{1}}属性来确保您的代码仅在值实际更改时执行一次。我认为这是一个很好的解决方案,因为它避免了必须子类化或添加新属性。

.selected

这里是Swift:

 //Add action for `ValueChanged`
 [toggleSwitch addTarget:self action:@selector(switchTwisted:) forControlEvents:UIControlEventValueChanged];

 //Handle action
- (void)switchTwisted:(UISwitch *)twistedSwitch
{
    if ([twistedSwitch isOn] && (![twistedSwitch isSelected]))
    {
        [twistedSwitch setSelected:YES];

        //Write code for SwitchON Action
    }
    else if ((![twistedSwitch isOn]) && [twistedSwitch isSelected])
    {
        [twistedSwitch setSelected:NO];

        //Write code for SwitchOFF Action
    }
}

答案 3 :(得分:9)

如果您在应用中使用了这么多开关,那么在所有地方更改代码都会出现问题 定义了UISwitch的动作方法。只有在值发生变化时,才能进行自定义切换和处理事件。

CustomSwitch.h

#import <UIKit/UIKit.h>

@interface Care4TodayCustomSwitch : UISwitch
@end

CustomSwitch.m

@interface CustomSwitch(){
    BOOL previousValue;
}
@end

@implementation CustomSwitch



- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        previousValue = self.isOn;
    }
    return self;
}


-(void)awakeFromNib{
    [super awakeFromNib];
    previousValue = self.isOn;
    self.exclusiveTouch = YES;
}


- (void)setOn:(BOOL)on animated:(BOOL)animated{

    [super setOn:on animated:animated];
    previousValue = on;
}


-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{

    if(previousValue != self.isOn){
        for (id targetForEvent in [self allTargets]) {
            for (id actionForEvent in [self actionsForTarget:targetForEvent forControlEvent:UIControlEventValueChanged]) {
                [super sendAction:NSSelectorFromString(actionForEvent) to:targetForEvent forEvent:event];
            }
        }
        previousValue = self.isOn;
    }
}

@end

如果值与更改的值相同,我们将忽略事件。在故事板中的所有类UISwitch中输入CustomSwitch。这将解决问题并在值更改时仅调用目标

答案 4 :(得分:7)

我遇到了许多面临同样问题的用户,所以可能是UISwitch的错误,所以我现在才发现它的临时解决方案。我发现一个gitHub自定义KLSwitch现在使用此希望苹果将在xCode的下一次更新中修复此问题: -

https://github.com/KieranLafferty/KLSwitch

答案 5 :(得分:6)

如果您不需要立即对交换机的值进行更改,则以下内容可能是一个解决方案:

- (IBAction)switchChanged:(id)sender {
  [NSObject cancelPreviousPerformRequestsWithTarget:self];

  if ([switch isOn]) {
      [self performSelector:@selector(enable) withObject:nil afterDelay:2];
  } else {
      [self performSelector:@selector(disable) withObject:nil afterDelay:2];
  }
}

答案 6 :(得分:3)

从iOS 9.3测试版开始,此问题仍然存在。如果您不介意用户无法在交换机外拖动,我发现使用.TouchUpInside而不是.ValueChanged可以正常工作。

答案 7 :(得分:2)

我在iOS 9.2中仍面临同样的问题

我得到了解决方案并且冒充,因为它可能会帮助其他人

  1. 创建计数变量以跟踪方法调用的次数

    int switchMethodCallCount = 0;
    
  2. 保存切换值的bool值

    bool isSwitchOn = No;
    
  3. 在Switch的值更改方法中,仅对第一个方法调用执行欲望操作。当切换值再次将设置计数值和t bool变量值更改为默认值

    - (IBAction)frontCameraCaptureSwitchToggle:(id)sender {
    
    
    
    //This method will be called multiple times if user drags on Switch,
    //But desire action should be perform only on first call of this method
    
    
    //1. 'switchMethodCallCount' variable is maintain to check number of calles to method,
    //2. Action is peform for 'switchMethodCallCount = 1' i.e first call
    //3. When switch value change to another state, 'switchMethodCallCount' is reset and desire action perform
    
    switchMethodCallCount++ ;
    
    //NSLog(@"Count --> %d", switchMethodCallCount);
    
    if (switchMethodCallCount == 1) {
    
    //NSLog(@"**************Perform Acction******************");
    
    isSwitchOn = frontCameraCaptureSwitch.on
    
    [self doStuff];
    
    }
    else
    {
    //NSLog(@"Do not perform");
    
    
    if (frontCameraCaptureSwitch.on != isSwitchOn) {
    
        switchMethodCallCount = 0;
    
        isSwitchOn = frontCameraCaptureSwitch.on
    
        //NSLog(@"Count again start");
    
        //call value change method again 
        [self frontCameraCaptureSwitchToggle:frontCameraCaptureSwitch];
    
    
        }
    }
    
    
    }
    

答案 8 :(得分:2)

This problem plagues me when I tie the switch to other behaviors. Generally things don't like to go from on to on. Here's my simple solution:

@interface MyView : UIView
@parameter (assign) BOOL lastSwitchState;
@parameter (strong) IBOutlet UISwitch *mySwitch;
@end

@implementation MyView

// Standard stuff goes here

- (void)mySetupMethodThatsCalledWhenever
{
    [self.mySwitch addTarget:self action:@selector(switchToggled:) forControlEvents:UIControlEventValueChanged];
}

- (void)switchToggled:(UISwitch *)someSwitch
{
    BOOL newSwitchState = self.mySwitch.on;
    if (newSwitchState == self.lastSwitchState)
    {
        return;
    }
    self.lastSwitchState = newSwitchState;

    // Do your thing
}

Just be sure to also set self.lastSwitchState every time you manually change mySwitch.on! :)

答案 9 :(得分:1)

此类问题通常由ValueChanged引起。您无需按此按钮即可运行该功能。这不是触摸事件。每次以编程方式将开关更改为开/关时,值都会更改,并再次调用IBAction函数。

@RoNiT得到了正确答案:

斯威夫特

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}

答案 10 :(得分:0)

DispatchQueue.main.async {
        self.mySwitch.setOn(false, animated: true)
    }

这样可以正常工作,并且不会再次调用选择器功能。

答案 11 :(得分:0)

这对我有用。

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
    self.switch.isOn = true
}