Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIGestureRecognizer firing twice?

Tags:

iphone

I've set up a UITapGestureRecognizer on viewDidLoad of my view controller but somehow it fires the selector method twice for a single tap.

UITapGestureRecognizer *g = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openInMapsApp:)] autorelease];
[self.mapView addGestureRecognizer:g];

My method:

-(void)openInMapsApp:(UIGestureRecognizer*)g {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
                                                    message:@"This will open this location in the Maps application. Continue?"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:@"OK",nil];
[alertView show];
[alertView release];
}
like image 574
Matthew Avatar asked Jul 11 '10 17:07

Matthew


3 Answers

Gesture recognizers send action with different gesture state. So it's not a bug. Workaround is:

 UITapGestureRecognizer *g = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openInMapsApp:)] autorelease];
[self.mapView addGestureRecognizer:g];

-(void)openInMapsApp:(UIGestureRecognizer*)g {
if(g.state != UIGestureRecognizerStateRecognized)
    return;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
                                                    message:@"This will open this location in the Maps application. Continue?"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:@"OK",nil];
[alertView show];
[alertView release];
}
like image 150
Nick Rostov Avatar answered Nov 05 '22 14:11

Nick Rostov


I was having a double UIAlertView come up. As shown by Nicolas Rostov above, this worked for me. Both the UIGestureRecognizerStateEnded and the UIGestureRecognizerStateRecognized states created a new alertView when [alertView show] was used in the block. With //[alertView show] commented out, both of them still showed up on the console, but only one action took place.

-(void) handleTapGesture:(UIGestureRecognizer*)sender{
    if(sender.state != UIGestureRecognizerStateRecognized)
    return;
like image 6
Roselle Tanner Avatar answered Nov 05 '22 14:11

Roselle Tanner


I can confirm the same. I submitted a bug report to Apple with a sample project demonstrating the issue.

The temporary workaround I've found is to disable the UITapGestureRecognizer immediately before showing the Alert. Then, in the UIAlertView delegate method(s) you implement, re-enable it. This requires you to keep track of the GR somehow, but it seems like the most elegant solution for the time-being.

Using the sample code above:

-(void)openInMapsApp:(UIGestureRecognizer*)g {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
                                                message:@"This will open this location in the Maps application. Continue?"
                                               delegate:self
                                      cancelButtonTitle:@"Cancel"
                                      otherButtonTitles:@"OK",nil];
    g.enabled = NO;
    self.activeGestureRecognizer = g;
    [alertView show];
    [alertView release];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    self.activeGestureRecognizer.enabled = YES;
    self.activeGestureRecognizer = nil;
}

- (void)alertViewCancel:(UIAlertView *)alertView {
    self.activeGestureRecognizer.enabled = YES;
    self.activeGestureRecognizer = nil;
}
like image 4
gorbster Avatar answered Nov 05 '22 14:11

gorbster