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

35.2k Views Asked by At

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?

9

There are 9 best solutions below

0
On

To avoid this, you can add the UILongPressGestureRecognizer inside the cellForRowAtIndexPath instead of didSelectRowAtIndexPath

3
On

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
    }
}
0
On
let longPressGesture = UILongPressGestureRecognizer(target: self, action: (#selector(YourCustomeTableCell.longTap)))
self.addGestureRecognizer(longPressGesture)

func longTap(){
    print("Long tap")
}
0
On

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)
0
On

Using IBAction you can do (for a CollectionView):

@IBAction func handleLongPress(sender: AnyObject) {

    if sender.state == UIGestureRecognizerState.Began
    {
        let position = sender.locationInView(sender.view)

        if let indexPath : NSIndexPath = ((sender.view as! UICollectionView).indexPathForItemAtPoint(position))!{
            print("You holding cell #\(indexPath.item)!")
        }
    }
}

Remember to link with your Long Press Gesture Recognizer.

0
On

Swift 5

Declare this line in viewDidLoad() like this

override func viewDidLoad() {
        super.viewDidLoad()
//do other stuff here
        
        // long press listener for tableview
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:)))
        tableView.addGestureRecognizer(longPress)
        
    }

Where handleLongPress() method is

 @objc private func handleLongPress(sender: UILongPressGestureRecognizer) {
        if sender.state == .began {
            let touchPoint = sender.location(in: tableView)
            if let indexPath = tableView.indexPathForRow(at: touchPoint) {
                let alert = UIAlertController(title: "Alert", message: "Do you want to delete this item?", preferredStyle: .alert)
                
                let action = UIAlertAction(title: "Yes", style: .default) { (action) in
                    // do your functionality

                    alert.dismiss(animated: true, completion: nil)
                    
                }
                let actionDelete = UIAlertAction(title: "No", style: .default) { (action) in
                    // do your functionality
                    alert.dismiss(animated: true, completion: nil)
                    
                }

                alert.addAction(action)
                alert.addAction(actionDelete)
                self.present(alert, animated: true, completion: nil)
                // your code here, get the row for the indexPath or do whatever you want
            }
        }
    }

enter image description here

enter image description here

2
On

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

1
On

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)")
        }
    }
}
4
On

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
        }
    }
}