I have been trying to setup a long press gesture recognizer on UITableView. The gesture is working fine, but i want to disable the didSelectRowAtIndexPath delegate function of UITableView when Long Press gesture is recognised.
In short, if user single tap on the cell i have to push a new UIViewController, and if user long press on the cell i have to show an UIActionSheet.
extension GroupChatListingViewController : UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func setupLongPress() {
longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
longPressGesture.cancelsTouchesInView = false
self.tableView.addGestureRecognizer(longPressGesture)
}
func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
self.tableView.allowsSelection = false
let touchPoint = longPressGestureRecognizer.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
self.showActionSheet()
}
}
else if longPressGestureRecognizer.state == .ended {
self.tableView.allowsSelection = true
}
} }
This problem is very common, and the “accepted answer” in StackOverflow is one that set the tag of the button during cellForRowAtIndexPath:. This “misuse” of a view tag means you may not use viewWithTag:, and secondly it could have bug when you delete/move cells (because cellForRowAtIndexPath: will not be called).
The trick is to get the superview of the button, which will be the cell, and then using tableView.indexPathForCell (cell) to get the index path. @IBAction func tapOnButton(sender: UIButton) { let cell = sender.superview as! UITableViewCell let indexPath = tableView.indexPathForCell(cell) }
But the best answer is to create your custom UITableViewCell, then have your UIButton delegate the call to your view controller. This requires more code, and a custom class, but is the most correct. If you are tapping on any other UIView, you could handle similarly. But in this case, you cannot add the UIGestureRecognizer to the view on storyboard.
@optimus comment helped me to solve this problem, this is a very genuine situation of disabling didSelectRowAtIndexPath when long press gesture is recognised on the tableview cell which has not been answered on the Internet
override func viewDidLoad() {
super.viewDidLoad()
setupLongPress()
setupTapPress()
}
extension GroupChatListingViewController : UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func setupLongPress() {
longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
longPressGesture.cancelsTouchesInView = false
self.tableView.addGestureRecognizer(longPressGesture)
}
func setupTapPress() {
singlePressGesture = UITapGestureRecognizer(target: self, action: #selector(tapPress))
singlePressGesture.delegate = self
singlePressGesture.cancelsTouchesInView = false
self.tableView.addGestureRecognizer(singlePressGesture)
}
func tapPress(gesture: UIGestureRecognizer) {
if gesture.state == .ended {
let touchPoint = gesture.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
// do your task on single tap
}
}
}
func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizerState.began {
let touchPoint = longPressGestureRecognizer.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
self.showActionSheet()
}
}
} }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With