web-dev-qa-db-de.com

So entfernen Sie Gestenerkennung

SO füge ich einer Overlay-Ansicht einen Gestenerkenner hinzu. Wenn Sie auf dem Bildschirm tippen, möchte ich, dass diese Überlagerung entfernt wird. Das Hinzufügen eines Gestenerkenners setzt jedoch das "Touchup inside" und andere Klickereignisse außer Kraft. Ich brauche das zurück, deshalb muss ich den Erkenner entfernen. Ich kann diese Methode verwenden, aber ich habe ein Problem. Mein Code unten - 

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

}

Hier entferne ich die Überlagerung von der anderen Ansicht. 

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

Meine Frage ist, wie entferne ich die Gestenerkennung in der zweiten Methode? Ich kann den variablen Abgriff dieser Methode nicht übergeben, noch kann ich sie in der vorherigen Methode entfernen. Irgendwelche Hinweise? Ich bin mit ziemlich vielen veränderlichen Problemen geblieben, wenn es um Ereignisse geht.

48
CodeGeek123

Aus den WWDC 2015, Cocoa Touch Best Practices wird empfohlen, dass Sie eine Eigenschaft oder eine iVar behalten, wenn Sie später darauf zugreifen müssen, und verwenden Sie nicht viewWithTag:

Moto: Eigenschaften statt Tags

Dies erspart Ihnen einige Probleme:

  1. Wenn Sie mit mehreren Gesten arbeiten, entfernen Sie die Geste, die Sie direkt beim Zugriff auf die Eigenschaft wünschen, und entfernen Sie sie. (Ohne alle Gesten der Ansicht durchlaufen zu müssen, um die richtige zu entfernen)
  2. Das Finden der korrekten Geste durch das Tag bei Iteration ist sehr irreführend, wenn Sie mehrere Tags in Ansichten haben und Konflikte mit einem bestimmten Tag auftreten

(d. h.) Sie haben es zum ersten Mal mit Tags implementiert, und alles funktioniert wie erwartet. Später arbeiten Sie an einer anderen Funktionalität, die sagen lässt bricht dies und verursacht unerwünschtes Verhalten, das Sie nicht erwarten. Log gibt keine Warnung aus und das Beste, was Sie je nach Fall bekommen können, ist ein Absturz, der nicht erkannte Selektoren an Instanz sendet. Manchmal bekommst du keine davon.

Lösung

Deklarieren Sie den iVar

@implementation YourController {
    UITapGestureRecognizer *tap;
}

Richten Sie Ihre Ansicht ein

- (void) helpClicked {
    //Your customization code

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

Entfernen Sie die Geste direkt

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

Diese Schleife entfernt alle Gestenerkenner einer Ansicht

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

Deklarieren Sie eine ivarUITapGestureRecognizer *tap in Ihrem @interface.

Ändern Sie helpClicked in:

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

und dismissView zu:

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

EDIT: Ich denke, die Methode von Nhahtdh ist etwas eleganter im Vergleich zu dieser.

EDIT2: Es scheint, dass Sie [self addGestureRecognizer:tap] arbeiten, also bin ich der Ansicht, dass dies eine Unterklasse von UIView ist.

29
Rok Jarc

Swift Version:

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

Richten Sie die Überlagerungsansicht einfach einmal mit der Gestenerkennung ein, aber machen Sie die Überlagerungsansicht hidden . Wenn eine Ansicht ausgeblendet ist, erhält sie keine Berührung vom Benutzer. Machen Sie die Überlagerungsansicht nur sichtbar, wenn dies erforderlich ist, und machen Sie sie verborgen, wenn Sie sie nicht benötigen.

5
nhahtdh

Ihr Code sollte für die zweite Methode wahrscheinlich eher so aussehen:

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

Ich habe die Prüfung für UITapGestureRecognizer hinzugefügt, falls Ihre Klasse mehr als 1 UIGestureRecognizers verarbeitet und Sie dies nur entfernen möchten.

4
skram

Diese Arbeit für mich:

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

In 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

Wenn Sie die Ansicht erweitern können, versuchen Sie es folgendermaßen:

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

Es hat für mich funktioniert.

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