¿Cómo desencadenar la vista de llamada de MKAnnotationView sin tocar el pin?

Estoy trabajando en una MKMapView con el pin de color habitual como puntos de ubicación. Me gustaría poder mostrar la leyenda sin tocar el pin.

¿Cómo debo hacer eso? La llamada a setSelected:YES en la vista de anotación no hizo nada. Estoy pensando en simular un toque en el pin, pero no estoy seguro de cómo hacerlo.

Pero hay una trampa para que la solución de Benvolio funcione, el código

 for (id currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual:annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:FALSE]; } } 

debe - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView desde - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView y en ningún otro lugar.

La secuencia en la que se viewWillAppear varios métodos como viewWillAppear , viewDidAppear de UIViewController y - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView es diferente entre la primera vez que se carga el mapa con una ubicación particular y las veces posteriores en que se muestra el mapa con la misma ubicación Esto es un poco complicado.

Ok, aquí está la solución a este problema.

Para mostrar la MKMapView use MKMapView ‘s selectAnnotation:animated método selectAnnotation:animated .

Suponiendo que desea que se seleccione la última vista de anotación, puede poner el código a continuación:

 [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES]; 

en el delegado a continuación:

 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { //Here [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES]; } 

De acuerdo, para agregar correctamente la Llamada, debe llamar a selectAnnotation: animada después de que se hayan agregado todas las vistas de anotación, utilizando didAddAnnotationViews del delegado:

 - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{ for (id currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual: annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:YES]; } } } 

Después de probar una variedad de respuestas a este hilo, finalmente se me ocurrió esto. Funciona de manera muy confiable, aún no lo veo fallar:

 - (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views; { for(id currentAnnotation in aMapView.annotations) { if([currentAnnotation isEqual:annotationToSelect]) { NSLog(@"Yay!"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^ { [aMapView selectAnnotation:currentAnnotation animated:YES]; }); } } } 

El bloque se usa para retrasar un poco, ya que sin él, es posible que la llamada no se muestre correctamente.

Esto no funciona para mi. Sospecho que hay un error en la API de MapKit.

Consulte este enlace para ver los detalles de otra persona para quien esto no funciona: http://www.iphonedevsdk.com/forum/iphone-sdk-development/19740-trigger-mkannotationview-callout-bubble.html#post110447

–editar–

De acuerdo, después de joder con esto por un tiempo, esto es lo que he podido hacer funcionar:

 for (id currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual:annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:FALSE]; } } 

Tenga en cuenta que esto requiere implementar - (BOOL)isEqual:(id)anObject para su clase que implemente el protocolo MKAnnotation.

Si solo desea abrir la leyenda de la última anotación que agregó, intente esto y funciona para mí.

[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];

Leí la API cuidadosamente y finalmente encontré el problema:


Si la anotación especificada no está en pantalla y, por lo tanto, no tiene una vista de anotación asociada, este método no tiene ningún efecto.

Entonces puede esperar un tiempo (por ejemplo, 3 segundos) y luego realizar esta acción. Entonces funciona

El problema al llamar a selectAnnotation desde - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView es que, como su nombre lo indica, este evento solo se desencadena cuando se carga inicialmente su MapView, por lo que no podrá activar el texto de la anotación si agréguelo después de que MapView haya terminado de cargarse.

El problema al llamarlo desde - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views es que su anotación puede no aparecer en la pantalla cuando se selectAnnotation lo que hace que no tenga ningún efecto. Incluso si centra la región de MapView en la coordenada de la anotación antes de agregar la anotación, bastará con selectAnnotation ligeramente la configuración de la región de selectAnnotation para que se selectAnnotation antes de que la anotación sea visible en la pantalla, especialmente si se anima setRegion .

Algunas personas han resuelto este problema llamando a selectAnnotation después de un retraso como tal:

 -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { [self performSelector:@selector(selectLastAnnotation) withObject:nil afterDelay:1]; } -(void)selectLastAnnotation { [myMapView selectAnnotation: [[myMapView annotations] lastObject] animated:YES]; } 

Pero incluso así, puede obtener resultados raros, ya que la anotación puede tardar más de un segundo en aparecer en pantalla, dependiendo de varios factores, como la distancia entre la región anterior de MapView y la nueva, o la velocidad de su conexión a Internet.

Decidí hacer la llamada desde - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated ya que garantiza que la anotación está realmente en pantalla (suponiendo que establezca la región de MapView en la coordenada de la anotación) porque este evento se activa después de que setRegion (y su animación) haya terminado. Sin embargo, regionDidChangeAnimated se activa cada vez que cambia la región de su MapView, incluso cuando el usuario solo navega alrededor del mapa, por lo que debe asegurarse de tener una condición para identificar correctamente cuándo es el momento adecuado para activar la llamada de la anotación.

Así es como lo hice:

 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; } } 

De esta manera, se garantiza que su anotación estará en la pantalla en el momento en que se selectAnnotation , y la parte if (myAnnotationWithCallout) no garantiza ninguna configuración de región que no sea la que está en - (void)someMethod desencadenará la llamada.

Debido a algo así como el código mostrado por benvolioT, que sospecho que existe en el sistema, cuando utilicé selectAnnotation: animation: method, no mostró el callOut, supuse que el motivo era porque ya estaba seleccionado y estaba evitando pidiendo a MapView que vuelva a dibujar callOut en el mapa usando el título y el subtítulo de la anotación.

Entonces, la solución fue simplemente deseleccionarlo primero y volver a seleccionarlo.

Ejemplo: Primero, necesitaba hacer esto en el método touchMoved de Apple (es decir, cómo arrastrar un AnnotationView) para ocultar el callOut. (Simplemente usando annotation.canShowAnnotation = NO solo no funciona, ya que sospecho que necesita volver a dibujar. La anulación de la selección provoca la acción necesaria. Además, deseleccionar solo no hizo ese truco, el callOut desapareció solo una vez y se volvió a dibujar inmediatamente. fue la sugerencia de que se volvió a seleccionar automáticamente).

 annotationView.canShowAnnotation = NO; [mapView deselectAnnotation:annotation animated:YES]; 

Entonces, simplemente usando el código de abajo en el método touchEnded no devolvió callOut (la anotación ha sido seleccionada automáticamente por el sistema para ese momento, y presumiblemente el redibujado de callOut nunca aparece):

 annotationView.canShowAnnotation = YES; [mapView selectAnnotation:annotation animated:YES]; 

La solución fue:

 annotationView.canShowAnnotation = YES; [mapView deselectAnnotation:annotation animated:YES]; [mapView selectAnnotation:annotation animated:YES]; 

Esto simplemente readquirió el callOut, presumiblemente reinició el proceso de redibujar el callOut por el mapView.

Estrictamente hablando, debería detectar si la anotación es la anotación actual o no (seleccionada, que sé que es) y si el callOut se está mostrando o no (lo cual no sé) y decido volver a dibujarlo en consecuencia, eso sería se mejor Sin embargo, aún no he encontrado el método de detección de callOut y tratar de hacerlo es algo innecesario en este momento.

La respuesta de Steve Shi me dejó en claro que selectAnnotation debe ser llamado desde el método mapViewDidFinishLoadingMap. Desafortunadamente no puedo votar pero quiero agradecerles aquí.

Restablecer las anotaciones también traerá la llamada al frente.

  [mapView removeAnnotation: currentMarker]; [mapView addAnnotation:currentMarker]; 

Simplemente agregue [mapView selectAnnotation: punto animado: YES];