The problem with calling selectAnnotation from - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView is that, as the name implies, this event is fired only after your MapView loads initially, so you cannot call the annotation leader if you add it after MapView has finished loading.
The problem with calling it from - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views is that your annotation may not appear on the screen when you selectAnnotation , which may lead to its invalidity. Even if you focus the MapView region on the coordinate of the annotation before adding the annotation, it takes a little delay to delay the region, which is necessary to trigger selectAnnotation before the annotation is visible on the screen, especially if you live setRegion .
Some people solved this problem by calling selectAnnotation after the delay itself:
-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { [self performSelector:@selector(selectLastAnnotation) withObject:nil afterDelay:1]; } -(void)selectLastAnnotation { [myMapView selectAnnotation: [[myMapView annotations] lastObject] animated:YES]; }
But even then, you may get strange results, since it might take more than one second for the annotation for the annotation to appear on the screen depending on various factors, such as the distance between your previous MapView area and the new one or the speed of your Internet connection.
I decided to make a call from - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated , because it ensures that the annotation is actually displayed on the screen (provided that you set the MapView area to the coordinate of the annotation), since this The event is fired after setRegion (and its animation) has finished. However, regionDidChangeAnimated triggered whenever the area of your MapView changes, including when the user just rolls around the map, so you need to make sure that you have the condition to correctly identify when the right time is coming to trigger the annotation callout .
Here is how I did it:
MKPointAnnotation *myAnnotationWithCallout; - (void)someMethod { MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init]; [myAnnotation setCoordinate: someCoordinate]; [myAnnotation setTitle: someTitle]; MKCoordinateRegion someRegion = MKCoordinateRegionMakeWithDistance (someCoordinate, zoomLevel, zoomLevel); myAnnotationWithCallout = myAnnotation; [myMapView setRegion: someRegion animated: YES]; [myMapView addAnnotation: myAnnotation]; } - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { if (myAnnotationWithCallout) { [mapView selectAnnotation: myAnnotationWithCallout animated:YES]; myAnnotationWithCallout = nil; } }
Thus, your annotation is guaranteed to be displayed on the screen at the time of the call to selectAnnotation , and the if (myAnnotationWithCallout) does not guarantee that an area parameter other than that located in - (void)someMethod will cause a callout.