1
votes

MKMapView provides the didSelectAnnotationView: method to report when the user first taps a pin. The result of this is that the map callout gets displayed. I need to let the user dismiss the map callout by tapping the pin a second time.

Unfortunately, the didSelectAnnotationView: method does not fire when the user taps a pin which is already selected.

2
Doesn't the callout go away when the user taps anywhere else on the map? I think this is automatic behavior, if I remember right. This would be a typical use case for dismissing the callout, I believe.Jim

2 Answers

1
votes

This is a non-standard behaviour and will confuse your users. Generally a tap outside the pin area de-selects the pin.

If you really want to do this, you could use the fact that 2 pins very close together (or in the exact same location) get selected in succession by two taps. You could put a fake pin behind the real one, which doesn't show a callout. I'm not sure exactly how this would work. You'd need to have the two pins aware of each other so that the top one always showed the callout.

0
votes

I had a similar problem, in that MKMapView's selection model didn't quite match my applications requirements. To work around this, what we need is a way to recognize taps on annotation views even if they are already selected. We can accomplish this by adding a UITapGestureRecognizer to each annotation view in the delegate method mapView:viewForAnnotation:

Depending on your interaction model, you might need to completely drive your UI using UITapGestureRecognizer, rather than using mapView:didSelectAnnotationView: and mapView:didDeselectAnnotationView: For example, I'm using a map view as a user picker. As such, selecting a user should move on to the next view controller, even if that user is already selected. Selection only provides visual feedback to the user.

- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    MKPinAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:@"pinAnnotationIdentifier"];

    if (annotationView == nil)
    {
        annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                             reuseIdentifier:kSPUserAnnotationViewMapViewReuseIdentifier];

        // need to be able to select annotations that are already selected;
        UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(annotationViewTapped:)];
        [annotationView addGestureRecognizer:tapRecognizer];
    } 

    return annotationView;
}

- (void)annotationViewTapped:(id)sender
{
    UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer*) sender;

        MKPinAnnotationView *userView = (MKPinAnnotationView*) tapRecognizer.view;
        [self userSelected:(MyUserModel*) userView.annotation];
    }
}