ios iphone ios7 xcode5 uiswitch

iOS7 UISwitch su Event ValueChanged: ¿Llamar continuamente es este Bug o qué...?



iphone xcode5 (11)

Editar

Ahora está arreglado en ios7.1
No hagas ningún ajuste para arreglarlo.

Edit2

Al parecer, el mismo problema ocurre nuevamente en iOS 8.0 y 8.1

Edit3

Ahora está arreglado en ios9.2
No hagas ningún ajuste para arreglarlo.

Hola Hoy UISwitch''s visto en UISwitch''s Evento ValueChanged: Llamar continuously mientras estoy en On a Off o Off en Activado y mi dedo se movió todavía en el lado derecho así como en el izquierdo. Asistí a la imagen GIF para obtener más información con NSLog.

Mi método de valor cambiado es:

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

iOS6 el mismo código de Switch funcionando bien como esperamos:

Entonces, ¿alguien puede sugerirme que llame solo una vez su estado On o Off? o es esto es un error o qué ...?

ACTUALIZAR

Aquí está mi demostración de esto:

programmatic Add UISwitch

de XIB agregando UISwitch


Este problema me atormenta cuando conecto el interruptor a otros comportamientos. En general, las cosas no les gusta ir de on a on . Aquí está mi solución simple:

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

¡Solo asegúrese de establecer self.lastSwitchState cada vez que cambie manualmente mySwitch.on ! :)


Este problema todavía está aquí a partir de iOS 9.3 beta. Si no le importa que el usuario no pueda arrastrar fuera del interruptor, creo que usar .TouchUpInside lugar de .ValueChanged funciona de manera confiable.


Este tipo de problema a menudo es causado por ValueChanged. No necesita presionar el botón para hacer que la función se ejecute. No es un evento táctil. Cada vez que programáticamente cambia el interruptor a on / off, el valor cambia y llama de nuevo a la función IBAction.

@RoNiT tuvo la respuesta correcta con:

Rápido

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


Mismo error aquí. Creo que encontré una solución simple. Solo tenemos que usar un BOOL nuevo que almacene el estado anterior del UISwitch y una declaración if en nuestra IBAction (Valor modificado disparado) para verificar que el valor del interruptor realmente haya cambiado.

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

No más comportamientos extraños. Espero eso ayude.


Por favor mira el siguiente código:

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


Puede usar la propiedad .selected para asegurarse de que su código solo se ejecute una vez cuando el valor real cambie. Creo que esta es una gran solución porque evita tener que crear subclase o agregar nuevas propiedades.

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

Y aquí está en Swift:

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


Si está utilizando tantos cambios en su aplicación, entonces hay un problema para cambiar el código en todos los lugares donde se define el método de acción t de UISwitch. Puede realizar un cambio personalizado y manejar los eventos solo si cambia el valor.

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

Estamos ignorando eventos si el valor es el mismo que el valor cambiado. Ponga CustomSwitch en toda la clase de UISwitch en el guión gráfico. Esto resolverá el problema y llamará al objetivo solo una vez cuando el valor haya cambiado.


Si no necesita reaccionar instantáneamente al cambio de valor del conmutador, lo siguiente podría ser una solución:

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


Tengo muchos usuarios que enfrentan el mismo problema, así que puede ser que este sea un error de UISwitch así que lo encontré ahora mismo para una solución temporal. Encontré un gitHub personalizado de KLSwitch use esto por ahora espero que Apple solucione esto en la próxima actualización de xCode: -

https://github.com/KieranLafferty/KLSwitch


Todavía estoy enfrentando el mismo problema en iOS 9.2

Tengo solución y planteo que podría ayudar a otros

  1. Crear variable de recuento para rastrear la cantidad de veces que el método recibió una llamada

    int switchMethodCallCount = 0;

  2. Ahorre el valor de bool para el valor del interruptor

    bool isSwitchOn = No;

  3. En el método de cambio de valor de Switch realice la acción de deseo para la primera llamada al método solamente. Cuando el valor del interruptor cambia de nuevo, establece el valor de conteo y el valor de la variable bool en predeterminado

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


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

Esto funciona bien y no llama a la función de selector de nuevo.