user3766930 user3766930 - 10 months ago 58
iOS Question

Why does my UITapGestureRecognizer doesn't work when I attach it to the element in my UITableViewCell?

I want to override the default behavior of double tapping the mapView.

In my

app I have a
in a static cell, so in the method
I've decided to add a
. This is how I do it:

func tableView(_ myTable: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if (indexPath as NSIndexPath).row == 0 {
let cell = myTable.dequeueReusableCell(withIdentifier: "cellStatic") as! MyTableDetailsCell

cell.mapView.isScrollEnabled = false //this works

//this does not:
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tap.numberOfTapsRequired = 2

And then I have a simple function:

func doubleTapped() {
print("map tapped twice")

But when I tap twice the map - it zooms in and there's no print in the console log - so my code doesn't work. What did I miss?

Answer Source

You had to enforce that your own double tap gesture recognizer disables the standard double tap gesture recognizer of the mapView.
This can be done using a delegate method:

Declare your view controller as a delegate of a gesture recognizer, using UIGestureRecognizerDelegate

Define a property for your own double tap gesture recognizer:

var myDoubleTapGestureRecognizer: UITapGestureRecognizer?  

Set up your double tap gesture recognizer, e.g. in viewDidLoad:

myDoubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
myDoubleTapGestureRecognizer!.numberOfTapsRequired = 2
myDoubleTapGestureRecognizer!.delegate = self

Note, that the delegate is set here.

Implement the following delegate method:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
                       shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    if ((gestureRecognizer == myDoubleTapGestureRecognizer) && (otherGestureRecognizer is UITapGestureRecognizer)) {
        let otherTapGestureRecognizer = otherGestureRecognizer as! UITapGestureRecognizer
        return otherTapGestureRecognizer.numberOfTapsRequired == 2
    return true

So, when you double tap the mapView, this delegate method returns true if the other gesture recognizer is the built-in double tap recognizer of the mapView. This means that the built-in double tap recognizer can only fire if your own double tap recognizer fails to recognize a double tap, which it won’t.
I tested it: The map is no longer zoomed, and method doubleTapped is called.