MKMapView MKPointAnnotation tap event MKMapView MKPointAnnotation tap event ios ios

MKMapView MKPointAnnotation tap event


There are two ways of detecting user interaction with your annotation view. The common technique is to define a callout (that standard little popover bubble that you see when you tap on a pin in a typical maps app) for your MKAnnotationView. And you create the annotation view for your annotation in the standard viewForAnnotation method:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{    if ([annotation isKindOfClass:[MKUserLocation class]])        return nil;    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];    annotationView.canShowCallout = YES;    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];    return annotationView;}

By doing this, you get a callout, but you're adding an right accessory, which is, in my example above, a disclosure indicator. That way, they tap on your annotation view (in my example above, a pin on the map), they see the callout, and when they tap on that callout's right accessory (the little disclosure indicator in this example), your calloutAccessoryControlTapped is called (in my example below, performing a segue to some detail view controller):

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{    [self performSegueWithIdentifier:@"DetailsIphone" sender:view];}

That's a very typical user experience on the small iPhone screen.

But, if you don't like that UX and you don't want the standard callout, but rather you want something else to happen, you can define your MKAnnotationView so that a callout is not shown, but instead you intercept it and do something else (for example, on iPad maps apps, you might show some more sophisticated popover rather than the standard callout). For example, you could have your MKAnnotationView not show a callout:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{    if ([annotation isKindOfClass:[MKUserLocation class]])        return nil;    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];    annotationView.canShowCallout = NO;    return annotationView;}

But you can then manually handle didSelectAnnotationView to detect when a user tapped on your MKAnnotationView, in this example showing a popover:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{    [mapView deselectAnnotation:view.annotation animated:YES];    DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"];    controller.annotation = view.annotation;    self.popover = [[UIPopoverController alloc] initWithContentViewController:controller];    self.popover.delegate = self;    [self.popover presentPopoverFromRect:view.frame                                  inView:view.superview                permittedArrowDirections:UIPopoverArrowDirectionAny                                animated:YES];}

I include some screen snapshots for the user interface yielded by the above code in my answer here.


Robs example for Swift 3:

class MapViewController: UIViewController{    override func viewDidLoad()    {        super.viewDidLoad()        // Create map view in storyboard        view.delegate = self    }}extension MapViewController: MKMapViewDelegate{    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?    {        let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotationView")        annotationView.canShowCallout = true        annotationView.rightCalloutAccessoryView = UIButton.init(type: UIButtonType.detailDisclosure)        return annotationView    }    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)    {        guard let annotation = view.annotation else        {            return        }        let urlString = "http://maps.apple.com/?sll=\(annotation.coordinate.latitude),\(annotation.coordinate.longitude)"        guard let url = URL(string: urlString) else        {            return        }        UIApplication.shared.openURL(url)    }}


Add button in this method

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {  pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];  pinView.canShowCallout = YES;}Then callout method- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{      InfoView *infoView = [[InfoView alloc]initWithNibName:@"InfoView" bundle:nil];        [self.navigationController pushViewController:infoView animated:YES];}