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

问题描述 投票:91回答:12

Edit

它现在固定在上 不要做任何调整来修复它。

Edit2

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

Edit3

它现在固定在上 不要做任何调整来修复它。


嗨今天我在UISwitch's事件中看到ValueChanged:当我改变continuouslyOnOff到On时调用Off,我的手指仍在右侧和左侧移动。我用NSLog更清楚地看了GIF图像。

我的价值改变方法是:

- (IBAction)changeSwitch:(id)sender{

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

}

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

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

UPDATE

这是我的演示:

programmatic Add UISwitch

from XIB adding UISwitch

ios iphone ios7 xcode5 uiswitch
12个回答
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
投票

此类问题通常由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
    }
}

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

这很好用,不会再次调用选择器功能。


0
投票

这对我有用。

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

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;
 }

没有更奇怪的行为。希望能帮助到你。


12
投票

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

 //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
    }
}

这里是Swift:

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

9
投票

如果您在应用程序中使用了这么多切换,那么在定义了UISwitch的t action方法的所有位置都会出现更改代码的问题。只有在值更改时,您才能进行自定义切换并处理事件。

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。这将解决问题并在值更改时仅调用目标一次


7
投票

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

https://github.com/KieranLafferty/KLSwitch


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];
  }
}

3
投票

从iOS 9.3 beta开始,此问题仍然存在。如果您不介意用户无法拖动开关,我发现使用.TouchUpInside而不是.ValueChanged可靠地工作。


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]; } } }

2
投票

当我将开关绑定到其他行为时,这个问题困扰着我。一般来说,不喜欢从onon。这是我的简单解决方案:

@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
}

每次手动更改self.lastSwitchState时,请务必设置mySwitch.on! :)

© www.soinside.com 2019 - 2024. All rights reserved.