Question

I am trying to show annotations on a mapView. All annotations come from JSON objects. They are divided into three groups. The user can select which annotations should be shown selecting an option on an segmentedIndex control.

As for now, the app is working as expected, the user selects an option from the segmentedIndex control, and the annotations are shown on the mapView.

My current issue is that I need the user to click on the callout view to open another viewController.

I think my code is right, but I guess it isn't then the showed callout view is the default calloutview, with title and subtitle. No action is fired when clicked on it.

Any help is welcome.

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

    static NSString *identifier = @"MyLocation";
    if ([annotation isKindOfClass:[PlaceMark class]]) {

        MKPinAnnotationView *annotationView =
        (MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:identifier];

        if (annotationView == nil) {
            annotationView = [[MKPinAnnotationView alloc]
                              initWithAnnotation:annotation
                              reuseIdentifier:identifier];
        } else {
            annotationView.annotation = annotation;
        }

        annotationView.enabled = YES;
        annotationView.canShowCallout = YES;

        // Create a UIButton object to add on the
        UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        [rightButton setTitle:annotation.title forState:UIControlStateNormal];
        [annotationView setRightCalloutAccessoryView:rightButton];

        UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
        [leftButton setTitle:annotation.title forState:UIControlStateNormal];
        [annotationView setLeftCalloutAccessoryView:leftButton];

        return annotationView;
    }

    return nil; 
}
- (void)mapView:(MKMapView *)mapView
 annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {

    if ([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure){
        // Do your thing when the detailDisclosureButton is touched
        UIViewController *mapDetailViewController = [[UIViewController alloc] init];
        [[self navigationController] pushViewController:mapDetailViewController animated:YES];

    } else if([(UIButton*)control buttonType] == UIButtonTypeInfoDark) {
        // Do your thing when the infoDarkButton is touched

        NSLog(@"infoDarkButton for longitude: %f and latitude: %f",
              [(PlaceMark*)[view annotation] coordinate].longitude,
              [(PlaceMark*)[view annotation] coordinate].latitude);
    }
}
Was it helpful?

Solution

Most likely the map view's delegate is not set in which case it won't call viewForAnnotation and will instead create a default view (red pin with a callout showing only the title and subtitle -- no buttons).

The declaration in the header file does not set the map view's delegate. That just tells the compiler that this class intends to implement certain delegate methods.

In the xib/storyboard, right-click on the map view and connect the delegate outlet to the view controller or, in viewDidLoad, put mapView.delegate = self;.


Unrelated, but I want to point out that in calloutAccessoryControlTapped, rather than checking the buttonType, you probably want to just know whether it's the right or left button so just do:

if (control == view.rightCalloutAccessoryView) ... 

See https://stackoverflow.com/a/9113611/467105 for a complete example.

There are at least two problems with checking the buttonType:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top