49

I want to wire an action such that if the gesture is a tap, it does animates an object in a particular way but if the press duration was more than .5 secs it does something else.

Right now, I just have the animation hooked up. I don't know how I can differentiate between a long press and a tap? How do I access the press duration to achieve the above?

 @IBAction func tapOrHold(sender: AnyObject) {
        UIView.animateKeyframesWithDuration(duration, delay: delay, options: options, animations: {

            UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {

                self.polyRotate.transform = CGAffineTransformMakeRotation(1/3 * CGFloat(M_PI * 2))
            })
            UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
                self.polyRotate.transform = CGAffineTransformMakeRotation(2/3 * CGFloat(M_PI * 2))
            })
            UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
                self.polyRotate.transform = CGAffineTransformMakeRotation(3/3 * CGFloat(M_PI * 2))
            })

            }, completion: { (Bool) in
                let vc : AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("NextView")
                self.showViewController(vc as UIViewController, sender: vc)
        })
blue_zinc
  • 2,410
  • 4
  • 30
  • 38

4 Answers4

103

Define two IBActions and set one Gesture Recognizer to each of them. This way you can perform two different actions for each gesture.

You can set each Gesture Recognizer to different IBActions in the interface builder.

@IBAction func tapped(sender: UITapGestureRecognizer)
{
    println("tapped")
    //Your animation code.
}

@IBAction func longPressed(sender: UILongPressGestureRecognizer)
{
    println("longpressed")
    //Different code
}

Through code without interface builder

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapped:")
    self.view.addGestureRecognizer(tapGestureRecognizer)
    
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
    self.view.addGestureRecognizer(longPressRecognizer)

func tapped(sender: UITapGestureRecognizer)
{
    println("tapped")
}

func longPressed(sender: UILongPressGestureRecognizer)
{
    println("longpressed")
}

Swift 5

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
self.view.addGestureRecognizer(tapGestureRecognizer)
    
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed))
self.view.addGestureRecognizer(longPressRecognizer)
    
@objc func tapped(sender: UITapGestureRecognizer){
    print("tapped")
}

@objc func longPressed(sender: UILongPressGestureRecognizer) {
    print("longpressed")
}
Gius
  • 89
  • 1
  • 1
  • 11
rakeshbs
  • 24,392
  • 7
  • 73
  • 63
  • 6
    This doesn't seem to work correctly as if I long press, both the tap and the long press fire... – blue_zinc Jan 21 '15 at 14:57
  • did you bind different IBActions for each Gesture Recogniser like in the code above. It works for me – rakeshbs Jan 21 '15 at 16:07
  • 4
    Thanks for adding the code version as well, was only finding interface builder answers and starting to get frustrated – jolyonruss Feb 03 '15 at 09:52
  • I have a table, in cellForRowAtIndexPath method I have written the code u suggested. How can I send the rowId to the action function ? @rakeshbs – Dipen Gajjar Jan 11 '17 at 10:14
  • 4
    @blue_zinc this solves the problem: tapGestureRecognizer.require(toFail: longPressRecognizer) – 93sauu Jan 07 '19 at 12:19
26

For swift2

let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.featuredCouponColView.addGestureRecognizer(lpgr)

Action

//MARK: - UILongPressGestureRecognizer Action -
    func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
        if gestureReconizer.state != UIGestureRecognizerState.Ended {
            //When lognpress is start or running
        }
        else {
            //When lognpress is finish
        }
    }

For Swift 4.2/ Swift 5

let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.colVw.addGestureRecognizer(lpgr)

//MARK: - UILongPressGestureRecognizer Action -
    @objc func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
        if gestureReconizer.state != UIGestureRecognizer.State.ended {
            //When lognpress is start or running
        }
        else {
            //When lognpress is finish
        }
    }
Hardik Thakkar
  • 15,269
  • 2
  • 94
  • 81
9

Through code without interface builder

// Global variables declaration
var longPressed = false
var selectedRow = 0



override func viewDidLoad() {
        super.viewDidLoad()  
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ContactListTableViewController.handleLongPress(_:)))
        longPressGesture.minimumPressDuration = 1.0 // 1 second press
        longPressGesture.allowableMovement = 15 // 15 points
        longPressGesture.delegate = self
        self.tableView.addGestureRecognizer(longPressGesture)
    }

// Long tap work goes here !!
if (longPressed == true) {

       if(tableView.cellForRowAtIndexPath(indexPath)?.accessoryType == .Checkmark){
                tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
                self.selectedRow -= 1

                if(self.selectedRow == 0){
                    self.longPressed = false
                }

            } else {
                self.selectedRow += 1
                tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
            }

        } else if(self.selectedRow == 0) {
          // Single tape work goes here !!
        }

But the only problem is the long press gesture runs two times. If you have found any solution do comment below !

AsimRazaKhan
  • 2,154
  • 3
  • 22
  • 36
0

Swift 5 using interface builder

for the normal tap you can simply create a touch up inside action from your button.

for the long press, create an outlet for your button, create the tap gesture recognizer and set it to the button then create the selector method to perform the long press tasks.

@IBOutlet var myButton: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()
    
    let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(addToListButtonLongPress(_:)))
    longPressRecognizer.numberOfTouchesRequired = 1
    longPressRecognizer.allowableMovement = 10
    longPressRecognizer.minimumPressDuration = 0.5
    myButton.addGestureRecognizer(longPressRecognizer)
}

// Connected to myButton in interface builder.
@IBAction func myButtonTapped(_ sender: UIButton) {
    print("button tapped")
}

@objc func myButtonLongPressed(_ sender: UILongPressGestureRecognizer) {
    print("button long pressed")
}
rBalmer
  • 67
  • 9