0

I am trying to add UILongGestureRecognizer to my Custom CollectionView Cell but handler function never called. This is my gesture and handlerFunc from custom cell:

let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))

@objc func handleLongPress(_ recognizer: UILongPressGestureRecognizer) {
    switch recognizer.state {
    case .possible:
        break
    case .began:
        print("began")
        break
    case .changed:
        break
    case .ended:
        print("ended")
        break
    case .cancelled:
        break
    case .failed:
        break
    @unknown default:
        break
    }
}

Also, this is my cell configure function:

func configure(with viewModel: RecordsCollectionViewCellViewModel, itemCount: Int) {
    longPress.numberOfTapsRequired = 1
    longPress.minimumPressDuration = 0.3
    longPress.delaysTouchesBegan = true
    longPress.delegate = self
    
    self.bringSubviewToFront(gestureView)
    gestureView.isUserInteractionEnabled = true
    gestureView.addGestureRecognizer(longPress)

}

The gestureView is the transparent view at the top of the cell.

Picode
  • 1,140
  • 1
  • 6
  • 12

3 Answers3

0

I've tried this in the past and had issues, I believe to do with contextMenu interaction on the actual collectionView.

You can fix it by putting the gesture handler on the collectionView itself and getting the gesture location, then cell at location as per this link;

how-to-make-tableviewcell-handle-both-tap-and-longpress

kric
  • 114
  • 5
0

If you are looking for the best solution, I think there are better solutions such as adding the UILongPressGestureRecognizer to the collection view and figuring out which cell was tapped or if you need to present some options on long tap func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath and reason they are recommended because there is already some gesture management on the collection view.

However, if you have considered all of this and still feel your solution is the right one for you, I think the issue is with this line let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:))) which seems to be initialized by default along with a cell.

I feel maybe when the cell is getting reused, something is not getting configured right in func configure

I would do these changes:

func configure(with viewModel: RecordsCollectionViewCellViewModel, itemCount: Int) {

        // Remove any previous gesture recognizers, maybe this is not needed 
        gestureView.gestureRecognizers?.removeAll()

        // Initialize a new gesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self,
                                                     action: #selector(handleLongPress))
        
        // longPress.numberOfTapsRequired = 1 - not needed
        
        longPress.minimumPressDuration = 0.3
        
        // longPress.delaysTouchesBegan = true - not needed
        
        // longPress.delegate = self - not needed unless you are doing something else
        
        gestureView.isUserInteractionEnabled = true
        
        gestureView.addGestureRecognizer(longPress)
}

Give this a try and see now if you function handleLongPress is being called ? On my end this works.

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
0

only call setLongPress() in viewDidLoad()

func setLongPress(){
     let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
     lpgr.minimumPressDuration = 0.5
     lpgr.delaysTouchesBegan = true
     lpgr.delegate = self
     self.CollectionView.addGestureRecognizer(lpgr)
}

@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer?) {
    if gestureRecognizer?.state != .ended {
        return
    }
    let p = gestureRecognizer?.location(in: projectCollectionView)

    let indexPath = CollectionView.indexPathForItem(at: p ?? CGPoint.zero)
    if indexPath == nil {
        print("couldn't find index path")
    } else {
        // get the cell at indexPath (the one you long pressed)
        var cell: UICollectionViewCell? = nil
        if let indexPath = indexPath {
            // your action here
        }
        // do stuff with the cell
    }
}