web-dev-qa-db-fra.com

Comment supprimer un identificateur de geste

SO, j'ajoute un identificateur de geste à une vue superposée. Lorsque je touche l'écran, je veux que cette superposition disparaisse. Cela dit, l'ajout d'un identificateur de geste annule les événements de "retouche à l'intérieur" et d'autres clics. J'ai besoin de ce retour donc j'ai besoin de retirergestgesturerecognizer. Je peux utiliser cette méthode mais j'ai un problème. Mon code ci-dessous - 

- (void)helpClicked
{
    CGRect visibleBounds = [self convertRect:[self bounds] toView:viewContainer];
    CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
    UIImageView * helpOverlay = [[UIImageView alloc]initWithFrame:CGRectMake(minimumVisibleX, 0, 1024, 768)];
    UIImage * helpImage = [UIImage imageNamed:@"HelpOverLay.png"];
    [helpOverlay setImage:helpImage];
    helpOverlay.tag = 50;
    self.scrollEnabled = NO;
    [self addSubview:helpOverlay]; 
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] 
                               initWithTarget:self
                               action:@selector(dismissView)];

[self addGestureRecognizer:tap];    

}

Ici, je retire la superposition de l’autre vue. 

- (void) dismissView
{
    UIView *overlay = [self viewWithTag:50];
    [overlay removeFromSuperview];
    self.scrollEnabled = YES;
}

Ma question est de savoir comment puis-je supprimer la reconnaissance de geste dans la deuxième méthode? Je ne peux pas passer le robinet variable dans cette méthode, ni je peux le supprimer dans la méthode précédente non plus. Des pointeurs? J'ai été confronté à pas mal de problèmes variables en ce qui concerne les événements.

48
CodeGeek123

À partir du WWDC 2015, Meilleures pratiques de Cocoa Touch , il est suggéré de conserver une propriété ou une iVar si vous devez y accéder ultérieurement, sans utiliser viewWithTag:

Moto: Propriétés au lieu de Tags

Cela vous évite des ennuis:

  1. Lorsque vous gérez plusieurs gestes, vous supprimez le geste que vous voulez directement lors de l'accès à la propriété, puis vous le supprimez. (Sans qu'il soit nécessaire d'itérer tous les gestes de la vue pour obtenir le geste correct à supprimer)
  2. Le fait de trouver le bon geste par balise lorsque vous effectuez une itération est très trompeur lorsque vous avez plusieurs balises sur des vues et lorsque vous rencontrez des conflits avec une balise spécifique.

(i.e) Vous l'avez implémenté pour la première fois avec des balises, et tout fonctionne comme prévu. Plus tard, vous travaillez sur une autre fonctionnalité qui dit brise cela et provoque un comportement indésirable auquel vous ne vous attendez pas. Bûche ne vous avertit pas, et la meilleure chose que vous puissiez obtenir, selon les cas, est un crash signalant le sélecteur non reconnu envoyé à l'instance. _ {Parfois, vous ne recevrez rien de tout cela}.

Solution

Déclarer l'ivar

@implementation YourController {
    UITapGestureRecognizer *tap;
}

Configurez votre vue

- (void) helpClicked {
    //Your customization code

    //Adding tap gesture
    tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissView)];
    [self addGestureRecognizer:tap];
}

Supprimer le geste directement

- (void) dismissView {
    [self.view removeGestureRecognizer:tap];
}
27
EridB

Cette boucle supprimera tous les identifiants de mouvements d’une vue

for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
    [self.view removeGestureRecognizer:recognizer];
}
102
Omar Abdelhafith

Déclarez une ivarUITapGestureRecognizer *tap dans votre @interface.

Remplacez helpClicked par:

- (void)helpClicked
{
    CGRect visibleBounds = [self convertRect:[self bounds] toView:viewContainer];
    CGFloat minimumVisibleX = CGRectGetMinX(visibleBounds);
    UIImageView * helpOverlay = [[UIImageView alloc]initWithFrame:CGRectMake(minimumVisibleX, 0, 1024, 768)];
    UIImage * helpImage = [UIImage imageNamed:@"HelpOverLay.png"];
    [helpOverlay setImage:helpImage];
    helpOverlay.tag = 50;
    self.scrollEnabled = NO;
    [self addSubview:helpOverlay]; 
    tap = [[UITapGestureRecognizer alloc] 
                               initWithTarget:self
                               action:@selector(dismissView)];

    [self addGestureRecognizer:tap];  
}

et dismissView à:

for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
    [self removeGestureRecognizer:tap];
}

EDIT: Je pense que la méthode de nhahtdh est un peu plus élégante par rapport à celle-ci.

EDIT2: il semble que [self addGestureRecognizer:tap] fonctionne, donc je suis en train de résumer ceci est une sous-classe de UIView.

29
Rok Jarc

Swift version:

if let recognizers = yourView.gestureRecognizers { 
  for recognizer in recognizers {
    yourView.removeGestureRecognizer(recognizer)
  }
}
5
budidino

Il vous suffit de configurer la vue superposition une fois, avec la reconnaissance de mouvements, mais de rendre la vue superposée hidden . Lorsqu'une vue est masquée, elle ne reçoit aucune touche de l'utilisateur. Rendez la vue superposée visible uniquement lorsque cela est nécessaire et masquée lorsque vous n'en avez pas besoin.

5
nhahtdh

Votre code devrait probablement ressembler davantage à ceci, pour la deuxième méthode:

- (void) dismissView {
  UIView *overlay = [self viewWithTag:50];

  for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
    if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
      [self removeGestureRecognizer:recognizer];
    }
  }

  [overlay removeFromSuperview];
  self.scrollEnabled = YES;
}

J'ai ajouté le contrôle pour UITapGestureRecognizer, au cas où votre classe gère plus de 1 UIGestureRecognizers et que vous ne vouliez que le supprimer.

4
skram

Ce travail pour moi:

for (UIGestureRecognizer *gr in self.view.gestureRecognizers) {
  [self.view removeGestureRecognizer:gr];
}
3
Matheus Veloza

Dans Swift 4

if let gestures = shotButton.gestureRecognizers //first be safe if gestures are there
    {
        for gesture in gestures //get one by one
        {
            shotButton.removeGestureRecognizer(gesture) //remove gesture one by one
        }
    }
1
iOS Lifee

Si vous parvenez à étendre la vue, essayez de cette façon:

_ = gestureRecognizers.flatMap { $0.map { removeGestureRecognizer($0) } }
1
Fran Pugl

Cela a fonctionné pour moi.

while (view.gestureRecognizers.count) {
  [view removeGestureRecognizer:[view.gestureRecognizers objectAtIndex:0]];
}
0
Adeel Ishaq