IOS7 UISwitch its event ValueChanged: constantly calling is an error or what ..?

Edit

Now it is fixed on
Do not try to fix it.

Edit2

Apparently, the same problem will recur in iOS 8.0 and 8.1.

Edit3

Now it is fixed on
Do not try to fix it.




Hi Today, I saw in UISwitch's Event ValueChanged: Calling continuously while I change from On to Off or Off to β€œOn” and my finger moves still on the right side, and also on the left side, I pinned the GIF image for more clear presentation in NSLog.

enter image description here

My modified method:

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

iOS6 the same switch code works as expected:

enter image description here

so can anyone suggest me that he only evokes his condition incl. or off or is it a mistake or what ..?

UPDATE

Here is my demo:

software Add UISwitch

from XIB adding UISwitch

+83
ios iphone ios7 xcode5 uiswitch
Oct 28 '13 at 6:22
source share
10 answers

I got a lot of users who are faced with one problem, so maybe this is a UISwitch error, so I found it only for a temporary solution. I found one gitHub custom KLSwitch use this, now I hope that apple will fix this in the next xCode update: -

https://github.com/KieranLafferty/KLSwitch

+7
Oct 28 '13 at 6:47
source share

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"); } } 
+44
Oct 28 '13 at 7:38
source share

Same error here. I think I found an easy workaround. We just need to use the new BOOL , which preserves the previous state of UISwitch and the if statement in our IBAction (Value Changed), to check if the value of the switch was really changed.

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

No more weird behavior. Hope this helps.

+12
Jan 17 '14 at 23:15
source share

You can use the UISwitch .selected property to make sure your code runs only once when the actual value changes. I think this is a great solution as it avoids subclassing or adding new properties.

  //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 he is in Swift:

 func doToggle(switch: UISwitch) { if switch.on && !switch.selected { switch.selected = true // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE } else { switch.selected = false } } 
+10
Nov 06 '15 at 8:21
source share

If you use so many switches in your application, then there is a problem with changing the code in all places where the UISwitch action method is defined. You can create a custom switch and handle events only if the value changes.

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 

We ignore events if the value is the same as the changed value. Put CustomSwitch in all UISwitch classes in the storyboard. This will solve the problem and trigger the goal only once when the value changes

+9
Mar 23 '14 at 22:05
source share

If you do not need to immediately respond to a change in the value of the switch, the following may be the 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]; } } 
+6
Nov 20 '13 at 17:21
source share

I am still facing the same issue in iOS 9.2

I got a solution and posed as this could help others

  • Create a counting variable to track the number of times the method received a call

     int switchMethodCallCount = 0; 
  • Save bool value for switch value

     bool isSwitchOn = No; 
  • In the method of changing the value of the switch, the desire action is performed only for the first method call. When the value of the switch again changes the value of the installation counter and the default value of the bool variable

     - (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' ie 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
Jan 19 '16 at 13:55
source share

This issue is still here, as is the beta version of iOS 9.3. If you don't mind that the user cannot drag outside the switch, I believe that using .TouchUpInside rather than .ValueChanged works reliably.

+2
Feb 19 '16 at 18:54
source share

This problem strikes me when I attach the switch to a different behavior. Usually things don't like going from on to on . Here is 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 remember to also set self.lastSwitchState every time you manually change mySwitch.on ! :)

+2
Apr 21 '16 at 21:55
source share

This type of problem is often caused by ValueChanged. You do not need to press a button to trigger a function. This is not a touch event. Each time you change the switch on / off programmatically, the value changes and it again calls the IBAction function.

@RoNiT had the correct answer:

Swift

 func doToggle(switch: UISwitch) { if switch.on && !switch.selected { switch.selected = true // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE } else { switch.selected = false } } 
+1
Jan 14 '17 at 13:11
source share



All Articles