Search code examples
swiftuicollectionviewlong-press

Swift 5 CollectionView get indexPath by longPress cell


I am looking way to get indexPath or data when i do longPress on cell. Basically i can to delete album from collectionView, to do that i need to get id.

My cellForItem

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AlbumCollectionViewCell", for: indexPath) as! AlbumCollectionViewCell
    cell.data = albumsDataOrigin[indexPath.row]

    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGetstureDetected))
    cell.addGestureRecognizer(longPressGesture)

    return cell
}

longPressGetstureDetected

@objc func longPressGetstureDetected(){
    self.delegateAlbumView?.longPressGetstureDetected()
}

delete func

func longPressGetstureDetected() {
    showAlertWith(question: "You wanna to delete this album?", success: {

        self.deleteAlbum() //Here i need to pass ID
    }, failed: {
        print("Delete cenceled")
    })
}

For people who looking complete answer

@objc func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {

    if longPressGestureRecognizer.state == UIGestureRecognizer.State.began {
        let touchPoint = longPressGestureRecognizer.location(in: collectionView)
        if let index = collectionView.indexPathForItem(at: touchPoint) {
            self.delegateAlbumView?.longPressGetstureDetected(id: albumsDataOrigin[index.row].id ?? 0)
        }
    }
}

Solution

  • Start by getting the coordinates of the press using gesture.location(in:) Ref: https://developer.apple.com/documentation/uikit/uigesturerecognizer/1624219-location

    Then use indexPathForItem(at:) to retrieve the IndexPath of the cell touched. Ref: https://developer.apple.com/documentation/uikit/uicollectionview/1618030-indexpathforitem

    Based on this you probably do not need a different gesture recognizer for each cell, you can probably register it with the collection view once.


    Solution provided by George Heints based on the above:

    @objc func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
    
        if longPressGestureRecognizer.state == UIGestureRecognizer.State.began {
            let touchPoint = longPressGestureRecognizer.location(in: collectionView)
            if let index = collectionView.indexPathForItem(at: touchPoint) {
                self.delegateAlbumView?.longPressGetstureDetected(id: albumsDataOrigin[index.row].id ?? 0)
            }
        }
    }
    

    I would recommend to use the State.recognized instead of State.began, your mileage may vary!