23

I would like to figure out how to println the indexPath of a UICollectionViewCell when I long press on a cell.

How can I do that in Swift?

I have looked all over for an example of how to do this; can't find one in Swift.

webmagnets
  • 2,172
  • 3
  • 29
  • 54
  • 1
    Show us what you've tried. – rdelmar Mar 24 '15 at 20:02
  • I have tried so many things it would be impossible to put all that in here. I have tried using the info at these links: http://stackoverflow.com/questions/23392485/change-background-of-uicollectionview-cell-on-tap - http://www.tagwith.com/question_73045_delete-uicollectionviewcell-with-uilongpressgesturerecognizer?ref=driverlayer.com/web - http://www.freshconsulting.com/create-drag-and-drop-uitableview-swift/ TONS of other pages. – webmagnets Mar 24 '15 at 20:05

7 Answers7

62

First you your view controller need to be UIGestureRecognizerDelegate. Then add a UILongPressGestureRecognizer to your collectionView in your viewcontroller's viewDidLoad() method

class ViewController: UIViewController, UIGestureRecognizerDelegate {

     override func viewDidLoad() {
         super.viewDidLoad()

        let lpgr = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
         lpgr.minimumPressDuration = 0.5
         lpgr.delaysTouchesBegan = true
         lpgr.delegate = self
         self.collectionView.addGestureRecognizer(lpgr)
    }

The method to handle long press:

func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
        if gestureReconizer.state != UIGestureRecognizerState.Ended {
            return
        }

        let p = gestureReconizer.locationInView(self.collectionView)
        let indexPath = self.collectionView.indexPathForItemAtPoint(p)

        if let index = indexPath {
            var cell = self.collectionView.cellForItemAtIndexPath(index)
            // do stuff with your cell, for example print the indexPath
             println(index.row)
        } else {
            println("Could not find index path")
        }
    }

This code is based on the Objective-C version of this answer.

Community
  • 1
  • 1
ztan
  • 6,673
  • 2
  • 21
  • 42
10

ztan answer's converted to swift 3 syntax and minor spelling update:

func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
    if gestureRecognizer.state != UIGestureRecognizerState.ended {
      return
    }

    let p = gestureRecognizer.location(in: collectionView)
    let indexPath = collectionView.indexPathForItem(at: p)

    if let index = indexPath {
      var cell = collectionView.cellForItem(at: index)
      // do stuff with your cell, for example print the indexPath
      print(index.row)
    } else {
      print("Could not find index path")
    }
}
Charles Martin
  • 308
  • 2
  • 13
chr0x
  • 855
  • 2
  • 11
  • 23
6

One thing I found was that:

if gestureReconizer.state != UIGestureRecognizerState.Ended {
    return
}

doesn't place pin until you release the longpress, which is OK, but I found

if gestureRecognizer.state == UIGestureRecognizerState.Began { }  

around the whole function will prevent multiple pin placements while letting the pin appear as soon as the timer delay is satisfied.

Also, one typo above: Reconizer -> Recognizer

Eric Aya
  • 68,765
  • 33
  • 165
  • 232
DPen
  • 449
  • 5
  • 4
  • You are absolutely right, it feels more like the native map to have the pin placed while you're still pressing rather than waiting until the press is released to place the pin. There is full Swift code here: http://stackoverflow.com/a/29466391/1359088 – James Toomey May 31 '16 at 03:18
4

The method handleLongProgress converted to swift 3 syntax works fine. I just want to add that the initialization of lpgr should be changed to:

let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gestureReconizer:)))
Fernando Cardenas
  • 1,025
  • 12
  • 14
2

Swift 5 & Swift 4 Table View Cell

override func viewDidLoad() {
    //MARK:- Add Long Gesture
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPressed))
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.allowableMovement = 15 // 15 points
    longPressGesture.delegate = self
    self.tablev.addGestureRecognizer(longPressGesture)
}


//MARK:- Long Press Gesture
@objc func longPressed(sender: UILongPressGestureRecognizer)
{

    if sender.state == UIGestureRecognizer.State.ended {
        return
    }
    else if sender.state == UIGestureRecognizer.State.began
    {
        let p = sender.location(in: self.tablev)
        let indexPath = self.tablev.indexPathForRow(at: p)

        if let index = indexPath {
            var cell = self.tablev.cellForRow(at: index)
            // do stuff with your cell, for example print the indexPath
            print(index.row)
            print("longpressed Tag: \(index.row)")
        } else {
            print("Could not find index path")
        }
    }
}
Shakeel Ahmed
  • 3,089
  • 24
  • 24
0

ztan answer's converted to swift 4 syntax and minor spelling update:

@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
    guard gestureRecognizer.state != .ended else { return }

    let point = gestureRecognizer.location(in: collectionView)

    if let indexPath = collectionView.indexPathForItem(at: point), 
       let cell = collectionView.cellForItem(at: indexPath) {
        // do stuff with your cell, for example print the indexPath
        print(indexPath.row)
    } else {
        print("Could not find index path")
    }
}
Artem
  • 942
  • 1
  • 7
  • 24
0

if objc func calling causes an error (Swift 5),

Replace Selector("handleLongPress") with #selector(self. handleLongPress) here is the full implementation.

in your viewDidLoad(),

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

and implement this in your viewcontroller,

@objc func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
        if gestureReconizer.state != UIGestureRecognizerState.Ended {
        return
    }

    let p = gestureReconizer.locationInView(self.collectionView)
    let indexPath = self.collectionView.indexPathForItemAtPoint(p)

    if let index = indexPath {
        var cell = self.collectionView.cellForItemAtIndexPath(index)
        // do stuff with your cell, for example print the indexPath
         println(index.row)
    } else {
        println("Could not find index path")
    }

 }
Cosmo Arun
  • 1,162
  • 13
  • 18