How To select a table row during a long press in Swift

33,944

Solution 1

Swift 4 & 5

override func viewDidLoad() {
    super.viewDidLoad()
    setupLongPressGesture()
}

func setupLongPressGesture() {
    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tblMessage.addGestureRecognizer(longPressGesture)
}

@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer){
    if gestureRecognizer.state == .began {
        let touchPoint = gestureRecognizer.location(in: self.tblMessage)
        if let indexPath = tblMessage.indexPathForRow(at: touchPoint) {
            
        }
    }
}

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    setupLongPressGesture()
}

func setupLongPressGesture() {
    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(YourViewController.handleLongPress(_:)))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tblMessage.addGestureRecognizer(longPressGesture)
}

func handleLongPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
    
    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began {
        
        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) {
            
            // your code here, get the row for the indexPath or do whatever you want
        }
    }
}

Objective - C

UILongPressGestureRecognizer* longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
[self.tableView addGestureRecognizer:longPressRecognizer];

-(void)onLongPress:(UILongPressGestureRecognizer*)pGesture
{
    if (pGesture.state == UIGestureRecognizerStateRecognized)
    {
    //Do something to tell the user!
    }

    if (pGesture.state == UIGestureRecognizerStateEnded)
    {
        UITableView* tableView = (UITableView*)self.view;
        CGPoint touchPoint = [pGesture locationInView:self.view];
        NSIndexPath* row = [tableView indexPathForRowAtPoint:touchPoint];
        if (row != nil) {
        //Handle the long press on row
        }
    }
}

Solution 2

The following code works fine for me:

Add a long press gesture recognizer in viewDidLoad:

// tapRecognizer, placed in viewDidLoad
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPress:")
self.view.addGestureRecognizer(longPressRecognizer)

Then the method invoke by the long press looks like this:

//Called, when long press occurred
func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {

    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began {

        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) {

            // your code here, get the row for the indexPath or do whatever you want
    }
}

Solution 3

Swift 3 function:

func handleLongPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {

    if longPressGestureRecognizer.state == UIGestureRecognizerState.Began {

        let touchPoint = longPressGestureRecognizer.locationInView(self.view)
        if let indexPath = tableView.indexPathForRowAtPoint(touchPoint) {

            // your code here, get the row for the indexPath or do whatever you want
    }
}

viewDidLoad:

let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(YourViewController.handleLongPress(_:)))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)

More: https://github.com/apple/swift-evolution/blob/e4328889a9643100177aef19f6f428855c5d0cf2/proposals/0046-first-label.md

Solution 4

Swift 4

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed(sender:)))
self.view.addGestureRecognizer(longPressRecognizer)

// MARK: Actions

@objc func longPressed(sender: UILongPressGestureRecognizer) {

    if sender.state == UIGestureRecognizerState.began {

        let touchPoint = sender.location(in: self.tableView)
        if let indexPath = tableView.indexPathForRow(at: touchPoint) {

            print("Long pressed row: \(indexPath.row)")
        }
    }
}

Solution 5

For Verision 3 of swift

func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
    if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
        let touchPoint = longPressGestureRecognizer.location(in: self.view)
        if let indexPath = notificationTabelView.indexPathForRow(at: touchPoint) {
            print("indexPath=\(indexPath)")
            // your code here, get the row for the indexPath or do whatever you want
        }
    }
}

In Your viewDidLoad function

let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(EmployeeNotificationViewController.longPress(_:)))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self as? UIGestureRecognizerDelegate
    self.notificationTabelView.addGestureRecognizer(longPressGesture)
Share:
33,944

Related videos on Youtube

LB79
Author by

LB79

Updated on August 07, 2021

Comments

  • LB79
    LB79 almost 3 years

    I have a table which has a long press gesture recogniser that runs code depending on what table row is selected.

    The trouble I'm having is that I currently have to tap the row I want then do the long press.

    How can I make the table select the row that I am long pressing without having to tap to select it first?

  • Shamsudheen TK
    Shamsudheen TK almost 9 years
    He is already achieved the functionality and facing the problem with an extra tap.
  • user3687284
    user3687284 almost 9 years
    I am not sure, if I understand the problem properly. What I can say at least is, that with my code I do a long press and I get the indexPath of the row on which I did the long press. No extra tap needed.
  • Vlad Fedoseev
    Vlad Fedoseev over 7 years
    let touchPoint = longPressGestureRecognizer.locationInView(self.tableView) is correct instead of let touchPoint = longPressGestureRecognizer.locationInView(self.view). Otherwise, you do not take into account that self.tableView.frame.origin mustn't be equal to CGPointZero
  • Sahil
    Sahil about 7 years
    It's not for swift 3.0 as you mentioned. it's still pointing to swift < 3.0
  • Ryan Pierce
    Ryan Pierce almost 7 years
    Worked perfectly in Swift 3 for me.
  • Ahmadreza
    Ahmadreza almost 6 years
    sender.location(in: self.tableView) // is correct
  • Ravi
    Ravi over 5 years
    Worked for me in just 5 Sec. Swift 4 Thanks Buddy!!
  • dronpopdev
    dronpopdev over 4 years
    The example for Swift 4 needs to be fixed. Need to delete line 'longPressGesture.delegate = self' and .ended replace on .began
  • mazend
    mazend about 4 years
    I agree with @DronPop. I confirmed that 'longPressGesture.delegate = self' is unnecessary for Swift4. In addition I also think '.began' is more appropriate. Anyways its a good answer so I up voted it.
  • Mehul Thakkar
    Mehul Thakkar almost 4 years
    i am not sure why, but i am getting indexPathForRowAtPoint value as nil