93 votes

iOS7 UISwitch son événement ValueChanged : L'appel continu est un bug ou quoi ?

Modifier

C'est maintenant fixé sur ios7.1
Ne faites pas d'ajustements pour le réparer.

Edit2

Apparemment, le même problème se reproduit dans iOS 8.0 et 8.1.

Edit3

C'est maintenant fixé sur ios9.2
Ne faites pas d'ajustements pour le réparer.


Bonjour Aujourd'hui, j'ai vu dans UISwitch's Événement ValueChanged: Appel à continuously alors que je suis en train de changer pour On a Off o Off sur On et mon doigt bougeait toujours du côté droit comme du côté gauche. J'ai joint l'image GIF pour plus de clarté avec NSLog.

enter image description here

Ma méthode de changement de valeur est :

- (IBAction)changeSwitch:(id)sender{

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

}

iOS6 le même code de Switch fonctionne bien comme nous l'attendions :

enter image description here

Quelqu'un peut-il me suggérer que l'appel ne soit activé ou désactivé qu'une seule fois, ou est-ce un bug ?

UPDATE

Voici ma démonstration :

programmatique Ajouter UISwitch

à partir de XIB en ajoutant UISwitch

0 votes

Avez-vous essayé de redémarrer xCode ?

0 votes

Ce n'est pas dans mon code, c'est probablement dans mon code et celui de mon frère aussi.

0 votes

Ya. Moi aussi j'ai eu le même problème quand j'ai essayé ici C'est peut-être un bug

45voto

AeroStar Points 77

Veuillez consulter le code suivant :

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

0 votes

Merci pour la réponse, comme je l'ai dit, j'ai essayé les deux méthodes et j'ai obtenu le même résultat. Je sais maintenant comment ajouter le programme swtich ainsi que le xib, monsieur.

12voto

nnarayann Points 161

Même bug ici. Je pense avoir trouvé une solution de contournement simple. Il suffit d'utiliser un nouveau BOOL qui stocke l'état précédent de la UISwitch et une instruction if dans notre IBAction (Valeur changée tirée) pour vérifier que la valeur du commutateur a effectivement changé.

previousValue = FALSE;

[...]

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

Plus de comportements bizarres. J'espère que cela vous aidera.

2 votes

Cela devrait juste dire if(mySwitch.on == previousValue)

9voto

codester Points 4528

Si vous utilisez un grand nombre de commutateurs dans votre application, il est difficile de modifier le code à tous les endroits où les commutateurs sont utilisés. Vous pouvez créer un commutateur personnalisé et gérer les événements uniquement si la valeur change.

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

Nous ignorons les événements si la valeur est la même que celle qui a été modifiée. Mettez CustomSwitch dans toutes les classes de UISwitch dans le storyboard. Cela résoudra le problème et n'appellera la cible qu'une seule fois lorsque la valeur a changé.

0 votes

Ça a marché pour moi. C'est idéal dans la mesure où cela n'entraîne pas l'ajout manuel de code superflu dans vos fichiers d'implémentation, car il est réutilisable et cache son implémentation dans l'implémentation de la classe. C'est tout simplement une bonne conception. Ce serait bien si cette réponse avait plus de commentaires, car je ne comprends pas vraiment pourquoi tout le code est là.

0 votes

Merci, ça a marché pour moi. Pouvez-vous expliquer le code un peu plus. @codester

7voto

Nitin Gohel Points 19461

J'ai beaucoup d'utilisateurs qui rencontrent le même problème. UISwitch J'ai donc trouvé une solution temporaire à ce problème. J'en ai trouvé un gitHub personnalisé KLSwitch utilisez ceci pour l'instant en espérant qu'apple corrigera ce problème dans la prochaine mise à jour de xCode :-)

https://github.com/KieranLafferty/KLSwitch

6voto

pre Points 2207

Si vous n'avez pas besoin de réagir instantanément au changement de valeur de l'interrupteur, la solution suivante peut être envisagée :

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

0 votes

Cela a fonctionné comme un charme dans iOS 11.2. Dans ma situation, il a déclenché 2 événements d'affilée (état : désactivé, balayage : désactivé, 1er événement : activé, 2ème événement : désactivé), donc un délai de 0,1 s est suffisant pour moi et non perceptible pour un utilisateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X