1

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

In my swift app I have a mapView in a static cell, so in the method cellForRowAt I've decided to add a UITapGestureRecognizer. 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
        cell.mapView.addGestureRecognizer(tap)
        ...

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?

user3766930
  • 5,629
  • 10
  • 51
  • 104
  • Try to set `UserInteractionEnabled` = `true` of `cell.mapView` – pkc456 Oct 18 '16 at 17:20
  • hm that didn't help... I already had it set up in storyboard, I also wrote it in the code, just to be sure, but without any success so far :| – user3766930 Oct 18 '16 at 17:31
  • Do you want to disable both scrolling and the double tap auto zoom of the map view? – Naveen Ramanathan Oct 18 '16 at 18:18
  • @NaveenRamanathan this is exactly what I want to do http://stackoverflow.com/questions/40074084/is-there-any-way-of-allowing-zooming-mkmapview-only-to-a-specific-region-while :) – user3766930 Oct 18 '16 at 18:48

3 Answers3

2

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
mapView.addGestureRecognizer(myDoubleTapGestureRecognizer!)

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.

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116
  • Reinhard, thank you very much for that, one question though - will the solution from here http://stackoverflow.com/questions/40074084/is-there-any-way-of-allowing-zooming-mkmapview-only-to-a-specific-region-while (merged with your suggestions) will work together? – user3766930 Oct 18 '16 at 19:05
  • I guess it would, since both problems seem to be completely independent. My suggested solution should only disable the built-in double tap gesture recognizer, and leave everything else intact. – Reinhard Männer Oct 18 '16 at 19:12
  • thank you, I will try it in a moment and let you know! – user3766930 Oct 18 '16 at 19:15
  • by the way, do you think that the same way I could block rotating the map? I cannot set it whit `cell.mapView.rotateEnabled = false` so maybe there's another way? – user3766930 Oct 18 '16 at 19:37
  • @user3766930 Glad to help you! So if you think the answer is correct, please accept it. To your 2nd question: I also thought that setting `rotateEnabled`to `false` would stop rotation. Sorry, but I have no idea why this is not the case. – Reinhard Männer Oct 18 '16 at 19:56
0

Try using touchesBegan to identify the touch event, and you can call your custom handler when the event is trigerred

Rakshith Nandish
  • 599
  • 3
  • 13
0

Add the mapview as a subview of a container view in the tableViewCell. Set constraints so that the mapview fills the entier container view. Disable the user interaction of the mapview and add the double tap gesture to the container view. This code will help.

    let cell = myTable.dequeueReusableCell(withIdentifier: "cellStatic") as! MyTableDetailsCell
    let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
    cell.mapView.isUserInteractionEnabled = false
    cell.containerView.addGestureRecognizer(tap)
    tap.numberOfTapsRequired = 2

Now the "doubleTapped" selector will be called when the mapview is tapped twice. All other user interactions including the rotation gesture of the mapview are disabled.

Naveen Ramanathan
  • 2,166
  • 1
  • 19
  • 21