UIGestureRecognizer发射两次?

时间:2010-07-11 17:50:53

标签: iphone

我已经在我的视图控制器的viewDidLoad上设置了一个UITapGestureRecognizer,但不知怎的,它只需点击两次选择器方法。

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

我的方法:

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

8 个答案:

答案 0 :(得分:19)

手势识别器以不同的手势状态发送动作。所以这不是一个错误。解决方法是:

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

答案 1 :(得分:6)

我有一个双UIAlertView出现。如上面的Nicolas Rostov所示,这对我有用。当UIGestureRecognizerStateEnded在块中使用时,UIGestureRecognizerStateRecognized[alertView show]状态都创建了新的alertView。随着// [alertView show]被注释掉,它们仍然出现在控制台上,但只发生了一个动作。

-(void) handleTapGesture:(UIGestureRecognizer*)sender{
    if(sender.state != UIGestureRecognizerStateRecognized)
    return;

答案 2 :(得分:4)

我可以确认一样。我向Apple提交了一个错误报告,其中有一个示例项目来证明这个问题。

我发现的临时解决方法是在显示警报之前立即禁用UITapGestureRecognizer。然后,在您实现的UIAlertView委托方法中,重新启用它。这需要你以某种方式跟踪GR,但它似乎是时间最优雅的解决方案。

使用上面的示例代码:

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

答案 3 :(得分:4)

我遇到了同样的问题,我注意到第二个事件的状态是UIGestureRecognizerStateCancelled(而第一个事件是UIGestureRecognizerStateEnded),所以另一种解决方法是在这种情况下忽略该事件。

答案 4 :(得分:3)

我刚刚解决了类似的问题。事实证明,我使用相同的调用将两个轻敲手势识别器添加到视图中。我发现的方法是在调用选择器时通过NSLogging手势识别器。

在您的位置,我会检查以确保您没有两个手势识别器 - 一个来自故事板,另一个以编程方式创建。

NSLog(@"recognizer: %@",[gestureRecognizer description]);

答案 5 :(得分:2)

我在视图中添加了一个计时器,用于检查触摸是否至少是半秒钟,如果太快则忽略第二次触摸。

这只是一种解决方法。我仍然想解决真正的问题。

答案 6 :(得分:1)

if(g.state != UIGestureRecognizerStateBegan)
//instead of if(g.state != UIGestureRecognizerStateRecognized)
return;

这将在手势事件后立即调用alertview。例如:如果您使用longtap事件,一旦您将手指关闭,将显示警报视图。但如果自动识别手势,将自动调用UIGestureRecognizerStateBegan状态。

答案 7 :(得分:-1)

我这样做并且工作了:

首先初始化存储最后一次滑动NSTimeInterval

的处理对象的成员
-(id)initWithResourcePath:(NSString*)path  {

    if ([super init]) {
        //some code


        lastSwipe = 0;
    }
    return self;

}

然后将此代码添加到您的方法

-(void)viewDetectedRightSwipe:(UISwipeGestureRecognizer*)recognizer {


//touch being registered    
NSTimeInterval thisTouch = [NSDate timeIntervalSinceReferenceDate];

//if the last swipe is the first swipe, then there's nothing to do but the handling of a correct gesture
if(lastSwipe !=0) {
    // find out how much time has passed between gestures
    NSTimeInterval timeSinceLastTouch = thisTouch -lastSwipe ;

    NSLog(@"thisTouch = %f",thisTouch);
    NSLog(@"timeSinceLastTouch = %f",timeSinceLastTouch);
    if (timeSinceLastTouch<0.2f) {
        //return if this is an invalid touch
        return;
    } else {
        // register the timestamp if it is valid
        lastSwipe = thisTouch;
        NSLog(@"left");
    }

} 
// invalid gestures won't be registed because they won't get to this portion of code.
lastSwipe = thisTouch;
NSLog(@"left");
// rest of the handling code
}