ios iOS7 UISwitch 其事件 ValueChanged:不断调用是这个错误还是什么..?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19628310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:38:10  来源:igfitidea点击:

iOS7 UISwitch its Event ValueChanged: Calling continuously is this Bug or what..?

iosiphoneios7xcode5uiswitch

提问by Nitin Gohel

Edit

编辑

It's now fixed on ios7.1
Don't do any tweak to fix it.

它现在已在ios7.1
上修复。不要做任何调整来修复它。

Edit2

编辑2

Apparently the same problem happens again in iOS 8.0 and 8.1

显然同样的问题在 iOS 8.0 和 8.1 中再次发生

Edit3

编辑3

It's now fixed on ios9.2
Don't do any tweak to fix it.

它现在已在ios9.2
上修复。不要做任何调整来修复它。



Hi Today i seen in UISwitch'sEvent ValueChanged:Calling continuouslywhile i am change to Onto Offor Offto On and my finger moved still on right side as well as left side. I atteched GIF image for more clear with NSLog.

今天,嗨,我看到在UISwitch's事件ValueChanged:中调用continuously,而我的改变OnOff或者Off到在我的手指还在移动在右侧和左侧。我使用 NSLog 获取了更清晰的 GIF 图像。

enter image description here

在此处输入图片说明

My Value Changed Method is:

我的价值改变方法是:

- (IBAction)changeSwitch:(id)sender{

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

}

iOS6 the same code of Switch working Fine as we expectation:

iOS6 的 Switch 代码如我们预期的一样工作正常:

enter image description here

在此处输入图片说明

so can anyone suggest me that call only one time its state On or off. or is this is a bug or what..?

所以任何人都可以建议我只调用一次它的状态打开或关闭。或者这是一个错误还是什么..?

UPDATE

更新

Here it is my Demo of it:

这是我的演示:

programmatic Add UISwitch

程序化添加 UISwitch

from XIB adding UISwitch

从 XIB 添加 UISwitch

采纳答案by Nitin Gohel

I got many user that facing same issue so may be this is bug of UISwitchso i found just now for temporary solution of it. I Found one gitHubcustom KLSwitchuse this for now hope apple will fix this in next update of xCode:-

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

https://github.com/KieranLafferty/KLSwitch

https://github.com/KieranLafferty/KLSwitch

回答by AeroStar

Please see the following code:

请看以下代码:

-(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");
    }
}

回答by nnarayann

Same bug here. I think I've found a simple workaround. We just have to use a new BOOLthat stores the previous state of the UISwitchand an if statement in our IBAction(Value Changed fired) to check that the value of the switch has actually changed.

同样的错误在这里。我想我找到了一个简单的解决方法。我们只需要使用一个 newBOOL来存储 之前的状态UISwitch和一个 if 语句在我们的IBAction(值改变被触发)中来检查开关的值是否真的改变了。

previousValue = FALSE;

[...]

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

No more weird behaviors. Hope it helps.

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

回答by itsji10dra

You can use the UISwitch's .selectedproperty to make sure your code only executes once when the value actual changes. I think this is a great solution because it avoids having to subclass or add new properties.

您可以使用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
    }
}

And here it is in Swift:

这是在 Swift 中的:

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

回答by codester

If you are using so many switch in your app then there is problem to change the code in all places where t action method of UISwitch is defined.You can make custom switch and handle the events only if value change.

如果你在你的应用程序中使用了这么多开关,那么在定义 UISwitch 的 t action 方法的所有地方更改代码都会有问题。你可以制作自定义开关并只有在值更改时才处理事件。

CustomSwitch.h

CustomSwitch.h

#import <UIKit/UIKit.h>

@interface Care4TodayCustomSwitch : UISwitch
@end

CustomSwitch.m

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

We are ignoring events if the value is same as changed value.Put CustomSwitch in all the class of UISwitch in storyboard.This will resolve the issue and call target only once when value changed

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

回答by pre

If you don't need to react instantly to the switch's value change the following could be a solution:

如果您不需要立即对开关的值更改做出反应,以下可能是一个解决方案:

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

回答by Nick Kohrn

This issue is still here as of iOS 9.3 beta. If you don't mind the user not being able to drag outside of the switch, I find that using .TouchUpInsiderather than .ValueChangedworks reliably.

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

回答by Ben Leggiero

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

当我将开关与其他行为联系起来时,这个问题困扰着我。一般来说,事情不喜欢从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
}

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

只要确保self.lastSwitchState每次手动更改时也设置mySwitch.on!:)

回答by Chetan Koli

I am still facing same problem in iOS 9.2

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

I got solution and posing as it might help others

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

  1. Create count variable to trace number of times method got call

    int switchMethodCallCount = 0;
    
  2. Save bool value for switch value

    bool isSwitchOn = No;
    
  3. In Switch's value change method perform desire action for first method call only. When switch value again changes set count value andt bool variable value to default

    - (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];
    
    
        }
    }
    
    
    }
    
  1. 创建计数变量以跟踪调用方法的次数

    int switchMethodCallCount = 0;
    
  2. 保存开关值的布尔值

    bool isSwitchOn = No;
    
  3. 在 Switch 的值更改方法中,仅对第一个方法调用执行期望操作。当 switch value 再次改变 set count value andt 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];
    
    
        }
    }
    
    
    }
    

回答by Dave G

This type of problem is often caused by ValueChanged. You don't need to press the button to cause the function to run. It's not a touch event. Every time you programmatically change the switch to on/off, the value changes and it calls the IBAction function again.

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

@RoNiT had the right answer with:

@RoNiT 给出了正确答案:

Swift

迅速

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