长按手势识别器在按下时被调用两次

387

我正在检测用户是否按下了2秒钟:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                             initWithTarget:self 
                                             action:@selector(handleLongPress:)];
        longPress.minimumPressDuration = 2.0;
        [self addGestureRecognizer:longPress];
        [longPress release];

这是我处理长按的方式:

-(void)handleLongPress:(UILongPressGestureRecognizer*)recognizer{
    NSLog(@"double oo");
}

当我按下按键超过2秒时,文本"double oo"会被打印两次。为什么会这样?我该如何解决?

7个回答

731

UILongPressGestureRecognizer是一个连续的事件识别器。您需要查看其状态以确定事件的开始、中间或结束,并相应地采取行动。例如,您可以在开始后放弃所有事件,或根据需要仅查看移动。请参阅Class Reference

长按手势是连续的手势。当指定时间(minimumPressDuration)内按下允许的手指数(numberOfTouchesRequired),且触摸点未超出可移动范围(allowableMovement)时,手势开始(UIGestureRecognizerStateBegan)。每当有一个手指移动时,手势识别器转换为Change状态。当任何一个手指抬起时,手势结束(UIGestureRecognizerStateEnded)。

现在您可以像这样跟踪状态

-  (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {
      NSLog(@"UIGestureRecognizerStateEnded");
    //Do Whatever You want on End of Gesture
     }
    else if (sender.state == UIGestureRecognizerStateBegan){
       NSLog(@"UIGestureRecognizerStateBegan.");
   //Do Whatever You want on Began of Gesture
     }
  }

4
下一个回答展示了如何操作,但我给这个回答点赞是因为它有详细的解释和文档链接。 - Matt Connolly
2
可以通过提供一个代码示例来更加有帮助,而不仅仅是链接到文档。我已经在下面发布了我的代码片段。检查UIGestureRecognizerStateBegan状态。 - Paul Solt
UIGestureRecognizerStateChanged - Rajneesh071
@joelm 你救了我) - Evgeniy Kleban
对于Swift 4: if (sender.state == UITapGestureRecognizer.State.ended ) { //在手势结束时进行任何操作 print("\n * 长按 *\n") } - Ravi

123

要检查UILongPressGestureRecognizer的状态,只需在选择器方法上添加if语句:

- (void)handleLongPress:(UILongPressGestureRecognizer *)sender {    
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}

13
由于状态不止 Ended,因此您不需要那个 if/else 块。当状态发生更改时,“长按检测”会打印多次。请改为检查 UIGestureRecognizerStateBegan 状态。 - Paul Solt
2
有人应该真正编辑一下那个答案,以符合顶部评论所说的内容。就目前而言,提供的代码是无法工作的。 - Declan McKenna

87

你需要检查正确的状态,因为每种状态的行为都不同。最有可能你需要使用 UILongPressGestureRecognizerUIGestureRecognizerStateBegan 状态。

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                             initWithTarget:self 
                                             action:@selector(handleLongPress:)];
longPress.minimumPressDuration = 1.0;
[myView addGestureRecognizer:longPress];
[longPress release];

...

- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
    if(UIGestureRecognizerStateBegan == gesture.state) {
        // Called on start of gesture, do work here
    }

    if(UIGestureRecognizerStateChanged == gesture.state) {
        // Do repeated work here (repeats continuously) while finger is down
    }

    if(UIGestureRecognizerStateEnded == gesture.state) {
        // Do end work here when finger is lifted
    }
}

2
似乎你需要移动手指才能改变状态;这正确吗? - Arcadian
当手指在周围移动时,它可能会触发StateChanged事件,这听起来与我在测试代码中所做的类似。 - Paul Solt
1
UIGestureRecognizerStateBegan 似乎只被调用了一次,这对于我的情况非常完美,在检测到按钮长按时尝试展示一个对话框。其他状态会被多次调用。谢谢! - Damian

20

只需尝试以下方法:

Objective-C

- (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}

Swift 2.2:

func handleLongPress(sender:UILongPressGestureRecognizer) {

        if (sender.state == UIGestureRecognizerState.Ended) {
            print("Long press Ended");
        } else if (sender.state == UIGestureRecognizerState.Began) {
            print("Long press detected.");
        }
}

18

Swift 3.0:

func handleLongPress(sender: UILongPressGestureRecognizer) {

    if sender.state == .ended {
        print("Long press Ended")
    } else if sender.state == .began {
        print("Long press detected")
    }

14

以下是在Swift中处理它的方法:

func longPress(sender:UILongPressGestureRecognizer!) {

        if (sender.state == UIGestureRecognizerState.Ended) {
            println("Long press Ended");
        } else if (sender.state == UIGestureRecognizerState.Began) {
            println("Long press detected.");
        }
}

7

您的手势处理程序会接收每个手势状态的调用。因此,您需要为每个状态设置检查并将代码放置在所需状态中。

最好使用switch-case而不是if-else:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                         initWithTarget:self 
                                         action:@selector(handleLongPress:)];
    longPress.minimumPressDuration = 1.0;
    [myView addGestureRecognizer:longPress];
    [longPress release];

-(void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
        switch(gesture.state){
          case UIGestureRecognizerStateBegan:
               NSLog(@"State Began");
               break;
          case UIGestureRecognizerStateChanged:
               NSLog(@"State changed");
               break;
          case UIGestureRecognizerStateEnded:
               NSLog(@"State End");
               break;
          default:
               break;
         }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接