1

I would like to capture taps on an MKMarkerAnnotationView, and not animate the view when this happens.

Through a delegate for my MKMapView, I can capture selection and deselection that are roughly equivalent to taps on the MKMarkerAnnotationView (the selection also happens when tapping the label that is not part of the MKMarkerAnnotationView)

I am trying to remove the default animation. I didn't find a straightforward solution.

I tried:

1/ setting the view to not selected during the selection. This does cancel the animation but further taps are not captured.

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    view.setSelected(false, animated: false)
    // or
    view.isSelected = false
    handleTap(view)
}

2/ adding another tap gesture recognizer on the view and preventing other gesture recognizers from receiving the touch. This works well unless I tap the label instead of the annotation view.

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let view = dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) as? MKMarkerAnnotationView ??
        MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
    view.annotation = annotation
    view.gestureRecognizers?.forEach { view.removeGestureRecognizer($0) }
    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap(gesture:)))
    gestureRecognizer.delegate = self
    view.addGestureRecognizer(gestureRecognizer)
    return view
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return false
}
sandpat
  • 1,478
  • 12
  • 30
Guig
  • 9,891
  • 7
  • 64
  • 126

2 Answers2

0

You can try override class:

final class CustomMarkerAnnotationView: MKMarkerAnnotationView {
  var onSelect: (() -> Void)?

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(false, animated: false)
    if selected {
      onSelect?() // or catch this in delegate
    }        
  }
}
Daniel Smith
  • 720
  • 7
  • 13
0

Overriding did not work for me. Here's what ultimately worked for me (Objc):

- (void)mapView:(MKMapView *)mapView
didSelectAnnotationView:(MKAnnotationView *)view
{
    //stops animation
    for( CALayer *sublayer in view.layer.sublayers )
    {
        [sublayer removeAllAnimations];
    }
    
    //stops selection
    [view setSelected:NO animated:NO];
}

For my own purposes I used the below instead, as it allows for properly deselecting the pin when tapping the pin again immediately after selection.

- (void)mapView:(MKMapView *)mapView
didSelectAnnotationView:(MKAnnotationView *)view
{
    //stops animation
    for( CALayer *sublayer in view.layer.sublayers )
    {
        [sublayer removeAllAnimations];
    }
    
    //stops selection
    [mapView deselectAnnotation:view.annotation animated:NO];
}
Rocksaurus
  • 53
  • 5