swiftmapkitmkmapviewuitapgesturerecognizermkmapviewdelegate

How to detect taps on MKMapView but ignore taps on MKAnnotationViews


I'm writing an iOS app where the user taps on an MKMapView to drop a pin (MKAnnotationView subclass), and taps an existing pin to delete it.

Adding new pins and deleting old ones is working, but the tap to delete an existing pin is also resulting in a new pin being dropped.

How can I update my code so the UITapGestureRecognizer detect taps on the map but ignore taps on map annotations?

I'm currently detecting taps on the MKMapView using a UITapGestureRecognizer:

@objc func tapHandler(_ gesture: UITapGestureRecognizer)
  {
    let location = recogniser.location(in: self.parent.mapView)
    let coordinate = self.parent.mapView.convert(location, toCoordinateFrom: self.parent.mapView)
    parent.shapeCoordinates.append(coordinate)
    self.redrawTheMap()
  }

I'm detecting taps on the pin using MKMapViewDelegate:

  func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView)
  {
    if let myAnnotation = view.annotation as? CustomAnnotation
    {
      parent.shapeCoordinates.remove(at: myAnnotation.index)
      self.redrawTheMap()
    }
  }

At the moment the UITapGestureRecognizer is picking up all taps on the MKMapView, regardless of whether they are on an MKAnnotationView or not.


Solution

  • Finally worked it out for myself. The trick was to use the UIGestureRecognizerDelegate to intercept the tap and decide whether or not the UITapGestureRecognizer should handle it.

    The following delegate method code checks what has been tapped on, and ignores it if it's an MKPinAnnotationView:

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
      {
        if (touch.view.self?.isKind(of: MKPinAnnotationView.self) == true)
        {
          return false
        }
        return true
      }