By Andrea


2011-05-30 17:52:40 8 Comments

I want to emulate a long a press button, how can I do this? I think a timer is needed. I see UILongPressGestureRecognizer but how can I utilize this type?

8 comments

@TheTiger 2012-05-18 14:59:24

Try this:

Adding button in viewDidLoad: like below

-(void)viewDidLoad {
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn setTag:1]; //you can set any integer value as tag number
    btn.title = @"Press Me";
    [btn setFrame:CGRectMake(50.0, 50.0, 60.0, 60.0)];

    // now create a long press gesture
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressTap:)];
    [btn addGestureRecognizer:longPress];
}

Now call the gesture method like this

-(void)longPressTap:(id)sender {
     UIGestureRecognizer *recognizer = (UIGestureRecognizer*) sender
    // Recogniser have all property of button on which you have clicked
    // Now you can compare button's tag with recogniser's view.tag  
    // View frame for getting the info on which button the click event happened 
    // Then compare tag like this
    if(recognizer.view.tag == 1) { 
       // Put your button's click code here
    }

    // And you can also compare the frame of your button with recogniser's view
    CGRect btnRect = CGRectMake(50.0, 50.0, 60.0, 60.0);
    if(recogniser.view.frame == btnRect) {
       //put your button's click code here
    }

   // Remember frame comparing is alternative method you don't need  to write frame comparing code if you are matching the tag number of button 
}

@rohan-patel 2013-03-20 11:32:40

recognizer.view.tag gives me wrong tag of UIButton clicked. Any solution?

@Suragch 2015-12-04 07:41:47

Swift version of the accepted answer

I made the additional modification of using UIGestureRecognizerState.Began rather than .Ended since that is probably what most users would naturally expect. Try them both and see for yourself, though.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add gesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
        self.button.addGestureRecognizer(longPress)

    }

    func longPress(gesture: UILongPressGestureRecognizer) {
        if gesture.state == UIGestureRecognizerState.began {
            print("Long Press")
        }
    }

    @IBAction func normalButtonTap(sender: UIButton) {
        print("Button tapped")
    }
}

@Bevan 2018-02-13 11:58:14

For Swift 4, the "func longPress" needs to be changed to make it work:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add guesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
        self.button.addGestureRecognizer(longPress)

    }

   @objc func longPress(_ guesture: UILongPressGestureRecognizer) {
        if guesture.state == UIGestureRecognizerState.began {
            print("Long Press")
        }
    }

    @IBAction func normalButtonTap(sender: UIButton) {
        print("Button tapped")
    }
}

@karan 2017-12-08 10:20:52

None worked hence I tried writing longpress code in IBAction or button click from storyboard in Controller instead of writing in viewDidLoad

- (IBAction)btnClick:(id)sender {

    tag = (int)((UIButton *)sender).tag;

// Long press here instead of in viewDidLoad

    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    longPress.cancelsTouchesInView = NO;
    [sender addGestureRecognizer:longPress];

}

@alondono 2014-11-05 12:18:03

As an alternative to the accepted answer, this can be done very easily in Xcode using Interface Builder.

Just drag a Long Press Gesture Recognizer from the Object Library and drop it on top of the button where you want the long press action.

Next, connect an Action from the Long Press Gesture Recognizer just added, to your view controller, selecting the sender to be of type UILongPressGestureRecognizer. In the code of that IBAction use this, which is very similar to the code suggested in the accepted answer:

In Objective-C:

if ( sender.state == UIGestureRecognizerStateEnded ) {
     // Do your stuff here
}

Or in Swift:

if sender.state == .Ended {
    // Do your stuff here
}

But I have to admit that after trying it, I prefer the suggestion made by @shengbinmeng as a comment to the accepted answer, which was to use:

In Objective-C:

if ( sender.state == UIGestureRecognizerStateBegan ) {
     // Do your stuff here
}

Or in Swift:

if sender.state == .Began {
    // Do your stuff here
}

The difference is that with Ended, you see the effect of the long press when you lift your finger. With Began, you see the effect of the long press as soon as the long press is caught by the system, even before you lift the finger off the screen.

@Dan Loughney 2015-09-22 13:53:02

I have a subclassed UIButton for my app, so I've pulled out my implementation. You can add this to your subclass or this could just as easily be recoded as a UIButton category.

My goal was to add the long press to my button without cluttering my view controllers with all of the code. I've decided that the action should be called when the gesture recognizer state begins.

There is a warning that comes out that I've never bothered to solve. Says it is a possible leak, thought I've tested the code and it doesn't leak.

@interface MYLongButton ()
@property (nonatomic, strong) UILongPressGestureRecognizer *gestureRecognizer;
@property (nonatomic, strong) id gestureRecognizerTarget;
@property (nonatomic, assign) SEL gestureRecognizerSelector;
@end

@implementation MYLongButton

- (void)addLongPressTarget:(CGFloat)interval target:(id)target action:(SEL)selector
{
    _gestureRecognizerTarget = target;
    _gestureRecognizerSelector = selector;
    _gestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)];
    _gestureRecognizer.minimumPressDuration = interval;

    [self addGestureRecognizer:_gestureRecognizer];
}

- (void)handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        NSAssert([_gestureRecognizerTarget respondsToSelector:_gestureRecognizerSelector], @"target does not respond to selector");

        self.highlighted = NO;

        // warning on possible leak -- can anybody fix it?
        [_gestureRecognizerTarget performSelector:_gestureRecognizerSelector withObject:self];
    }
}

To assign the action add this line to your viewDidLoad method.

[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];

The action should be defined like all IBActions (without the IBAction).

- (void)longPressAction:(id)sender {
    // sender is the button
}

@Jerry Juang 2015-05-24 08:22:26

I think you need my solution.

you should have this code for single press

- (IBAction)buttonDidPress:(id)sender {
    NSLog("buttonDidPress");
}

first, add long press gesture to button

- (void)viewWillAppear:(BOOL)animated
{
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
    [self.button addGestureRecognizer:longPress];
}

then call single press event repeatedly if long press gesture is recognized.

- (void)buttonDidLongPress:(UILongPressGestureRecognizer*)gesture
{
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
        {
            self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(buttonDidPress:) userInfo:nil repeats:YES];

            NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
            [theRunLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
        }
            break;
        case UIGestureRecognizerStateEnded:
        {
            [self.timer invalidate];
            self.timer = nil;
        }
            break;
        default:
            break;
    }
}

@WikipediaBrown 2019-03-06 21:50:23

You shouldn't add the UIGestureRecognizer during the viewWillAppear lifecycle event because whenever the view appears, another gesture recognizer will be added. This should be done in a private method that is called during initialization.

@Deepak Danduprolu 2011-05-30 18:27:38

You can start off by creating and attaching the UILongPressGestureRecognizer instance to the button.

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

And then implement the method that handles the gesture

- (void)longPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
         NSLog(@"Long Press");
    }
}

Now this would be the basic approach. You can also set the minimum duration of the press and how much error is tolerable. And also note that the method is called few times if you after recognizing the gesture so if you want to do something at the end of it, you will have to check its state and handle it.

@RecycleRobot 2013-05-24 12:25:22

Super! thanks! Btw: the if ( gesture.state == UIGestureRecognizerStateEnded ) is very important, otherwise you'll get alot of events in your longPress void

@shengbinmeng 2014-10-23 13:40:16

You maybe want to use if(gesture.state == UIGestureRecognizerStateBegan), because the user expects something happen when they are still pressing (the state Began), not when they release (Ended).

Related Questions

Sponsored Content

34 Answered Questions

[SOLVED] How do I create a basic UIButton programmatically?

11 Answered Questions

[SOLVED] How to set the title of UIButton as left alignment?

  • 2010-05-04 11:56:19
  • Madan Mohan
  • 192721 View
  • 444 Score
  • 11 Answer
  • Tags:   objective-c uibutton

19 Answered Questions

[SOLVED] UITextField text change event

7 Answered Questions

4 Answered Questions

6 Answered Questions

[SOLVED] In Objective-C, how do I test the object type?

  • 2009-07-17 17:19:34
  • James Skidmore
  • 234527 View
  • 538 Score
  • 6 Answer
  • Tags:   ios objective-c

2 Answered Questions

[SOLVED] UIButton long press with finger stationary

3 Answered Questions

[SOLVED] Long press gesture recognizer on UIButton?

1 Answered Questions

[SOLVED] Long and Short press on a UIBUTTON

1 Answered Questions

[SOLVED] uigesturerecognizer in iphone app

Sponsored Content