To disable the built-in callout from displaying, set canShowCallout
to NO
on the MKPinAnnotationView
/MKAnnotationView
in the viewForAnnotation
delegate method.
The next issue is that currently the code is always creating a new custom callout view and adding it to the selected annotation's view. This is why you get multiple callouts displaying at the same time (the ones on the previously selected annotations are not getting removed).
One solution is to keep a single instance of the custom callout view instead of creating a new one every time an annotation is selected. Then, just add/remove the callout view when an annotation is selected or de-selected.
Declare this single instance as a strong property in the view controller that contains the map view:
@property (nonatomic, strong) MyMapAnnotationViewController* mapAnnotationViewController;
Create the callout instance in viewDidLoad
(or viewWillAppear
if that works for you) but don't add it as a subview anywhere at this point -- just create it:
self.mapAnnotationViewController = [[MyMapAnnotationViewController alloc...
In didSelectAnnotationView
, instead of creating a new callout view instance, tell the existing instance to remove itself from its current superview (if any) and then add it to the new annotation's view:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
NSLog(@"ANNNOTATION VIEW : %@", view);
NSLog(@"VIEW ANNOTATION: %@", view.annotation);
[self.mapAnnotationViewController.view removeFromSuperview];
MyLocation* location = (MyLocation*)view.annotation;
[self.mapAnnotationViewController setTitle: [location title]];
[self.mapAnnotationViewController setRating:3.0];
//Since we are re-using the callout view,
//may need to do additional "cleanup" so that the callout
//shows the new annotation's data.
[view addSubview:self.mapAnnotationViewController.view];
}
Finally, you'll need to handle the case where the user de-selects an annotation by tapping on the map (instead of another annotation) and just remove the callout view:
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
[self.mapAnnotationViewController.view removeFromSuperview];
}
The viewForAnnotation
delegate method should look like this:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if (! [annotation isKindOfClass:[MyLocation class]])
{
//tell map view to show default view for annotations other than ours
//(like the user location blue dot)
return nil;
}
MKPinAnnotationView *pav = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pin"];
if (pav == nil)
{
pav = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
pav.canShowCallout = NO;
}
else
{
pav.annotation = annotation;
}
return pav;
}