386

I am detecting if the user has pressed down for 2 seconds:

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

This is how I handle the long press:

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

The text "double oo" gets printed twice when I press down for longer than 2 seconds. Why is this? How can I fix?

Sheehan Alam
  • 60,111
  • 124
  • 355
  • 556

7 Answers7

729

UILongPressGestureRecognizer is a continuous event recognizer. You have to look at the state to see if this is the start, middle or end of the event and act accordingly. i.e. you can throw away all events after the start, or only look at movement as you need. From the Class Reference:

Long-press gestures are continuous. The gesture begins (UIGestureRecognizerStateBegan) when the number of allowable fingers (numberOfTouchesRequired) have been pressed for the specified period (minimumPressDuration) and the touches do not move beyond the allowable range of movement (allowableMovement). The gesture recognizer transitions to the Change state whenever a finger moves, and it ends (UIGestureRecognizerStateEnded) when any of the fingers are lifted.

Now You Can Track The State Like This

-  (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
     }
  }
Crashalot
  • 33,605
  • 61
  • 269
  • 439
joelm
  • 8,741
  • 1
  • 19
  • 17
123

To check the state of the UILongPressGestureRecognizer just add an if statement on the selector method:

- (void)handleLongPress:(UILongPressGestureRecognizer *)sender {    
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}
shim
  • 9,289
  • 12
  • 69
  • 108
Dan
  • 1,271
  • 2
  • 8
  • 3
  • 13
    You don't want that if/else block, since there are more states than Ended. "Long press detected" will print multiple times when the state changes. Check the UIGestureRecognizerStateBegan state instead. – Paul Solt Aug 18 '11 at 20:59
  • 2
    Someone should really edit that answer to fit with what the top comment says. As it stands the code provided does not work. – Declan McKenna Sep 11 '12 at 22:40
86

You need to check the correct state, since there are different behaviors for each state. Most likely you're going to need the UIGestureRecognizerStateBegan state with the UILongPressGestureRecognizer.

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
    }
}
Paul Solt
  • 8,375
  • 5
  • 41
  • 46
  • 2
    Seems like you have to move your fingers to get the state to change; is that correct? – Arcadian Jan 18 '12 at 04:46
  • It might trigger StateChanged when moving fingers around, that sounds similar to what I was doing in my test code. – Paul Solt Jan 20 '12 at 04:12
  • 1
    UIGestureRecognizerStateBegan seems to only be called once which is perfect for my situation trying to show a dialog on detecting a long press on a button. The other states get called multiple times. Thanks! – Damian Mar 09 '12 at 13:29
20

Just try this:

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.");
        }
}
odemolliens
  • 2,581
  • 2
  • 32
  • 34
Rajesh Loganathan
  • 11,129
  • 4
  • 78
  • 90
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")
    }
Pang
  • 9,564
  • 146
  • 81
  • 122
fozoglu
  • 729
  • 5
  • 21
14

Here's how to handle it in Swift:

func longPress(sender:UILongPressGestureRecognizer!) {

        if (sender.state == UIGestureRecognizerState.Ended) {
            println("Long press Ended");
        } else if (sender.state == UIGestureRecognizerState.Began) {
            println("Long press detected.");
        }
}
Raj
  • 3,791
  • 5
  • 43
  • 56
7

your gesture handler receives call for each state of gesture. so you need to put a check for each state and put your code in required state.

One must prefer using switch-case over 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;
         }
}
RyanTCB
  • 7,400
  • 5
  • 42
  • 62
Pankaj Wadhwa
  • 3,073
  • 3
  • 28
  • 37