tutorial current annotation ios mapkit mkpinannotationview

ios - current - Se busca: Cómo seleccionar de manera confiable y consistente una anotación MKMapView



mapkit tutorial (7)

Después de llamar al método setCenterCoordinate: animated: (sin animación) de MKMapView , me gustaría llamar a SelectAnnotation: animated: (con animación) para que la anotación salga del marcador recientemente centrado.

Por ahora, simplemente observo mapViewDidFinishLoadingMap: y luego selecciono la anotación. Sin embargo, esto es problemático. Por ejemplo, este método no se llama cuando no hay necesidad de cargar datos de mapas adicionales. En esos casos, mi anotación no es seleccionada. :(

Muy bien. Podría llamar a esto inmediatamente después de establecer la coordenada central en su lugar. Ahh, pero en ese caso es posible que haya datos de mapas para cargar (pero aún no se ha terminado de cargar). Me arriesgaría a llamarlo demasiado pronto, con la animación volviéndose irregular en el mejor de los casos.

Por lo tanto, si entiendo correctamente, no es cuestión de saber si mi coordenada es visible, ya que es posible desviarse casi una pantalla llena de distancia y tener que cargar nuevos datos de mapas. Más bien, es una cuestión de saber si es necesario cargar nuevos datos de mapas y actuar en consecuencia.

¿Alguna idea sobre cómo lograr esto, o cómo (de manera confiable) seleccionar una anotación después de volver a centrar la vista del mapa en la coordenada donde vive esa anotación?

Se agradecen las pistas - ¡gracias!


Bueno, para tu información, esto es lo que dicen los documentos,

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 efecto.

Entonces, si quiero llamar a setCenterCoordinate:animated: o setRegion:animated: y luego quiero seleccionar la anotación llamando, selectAnnotation:animated: la anotación no se seleccionará y la llamada no aparecerá porque es exactamente lo mismo la razón mencionada anteriormente en los documentos, así que sería genial tener algo como, setCenterCoordinate:animated:ComletionBlock pero no está ahí ..! La forma en que funcionó para mí es la siguiente,

[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseInOut animations:^{ [self.mapView setCenterCoordinate:location.coordinate animated:YES]; } completion:^(BOOL finished) { [self.mapView selectAnnotation:location animated:YES]; }];

Esto le dará un bloque de finalización y u puede usar eso para seleccionar la anotación.



Estaba teniendo un problema similar. Estaba usando el MKPinAnnotationView predeterminado con animatesDrop: YES. Después de agregar las anotaciones al MKMapView, estaba haciendo esto:

[mapView selectAnnotation:[mapView.annotations objectAtIndex:1] animated:YES]

que en la lógica de mi programa, debe seleccionar la anotación más cercana. Esto no estaba funcionando. Descubrí el motivo: la vista de anotación no estaba en la pantalla en el momento de esta llamada de selección, debido a la animación de colocación de pin. Así que todo lo que hice fue configurar un temporizador para seleccionar la anotación un segundo después. Es un hack, pero funciona. Sin embargo, no estoy seguro de si funcionará en todas las situaciones, por ejemplo, en un 3G vs. 3G. Sería mejor averiguar la función de devolución de llamada correcta para ponerla.

selectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(selectClosestAnnotation) userInfo:nil repeats:NO]; - (void)selectClosestAnnotation { [mapView selectAnnotation:[mapView.annotations objectAtIndex:1] animated:YES]; }


He encontrado varios problemas con todas las soluciones que vi para mi problema (quiero seleccionar una anotación cuando la agregué desde viewDidAppear):

  1. Usando el mapView:didAddAnnotationViews: método delegado.

    Esto no me funcionó porque 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 efecto.

  2. Usando el método mapViewDidFinishLoadingMap: delegate.

    Esto tampoco me funcionó porque el mapa está en caché ahora, por lo que el método se llama solo una vez, la primera vez.

Solución:

John Blackburn estuvo muy cerca pero sin el mapView:didAddAnnotationViews: . Solo llamo a mi propio método selectAnnotation: antes de agregar la anotación, con un retraso:

[self.mapView addAnnotation:ann]; [self performSelector:@selector(selectAnnotation:) withObject:ann afterDelay:0.5];

Y esto es lo que hago en mi método selectAnnotation: :

- (void)selectAnnotation:(id < MKAnnotation >)annotation { [self.mapView selectAnnotation:annotation animated:YES]; }

Probado en dos iPhone 3GS (iOS 5 y 6) y un iPhone 5.


Lo que funcionó para mí fue llamar a selectAnnotation:animated: from mapView:didAddAnnotationViews: method:

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

Documentación de Apple sobre el mismo here .

Tenga en cuenta que solo tenía una anotación en el mapa, por lo que [[mapView annotations] lastObject] estaba bien para mis propósitos. Su experiencia puede ser diferente.


Me encontré con el mismo problema, pero encontré lo que parece una solución confiable y razonable:

  1. Implementar el método delegado mapView: didAddAnnotationViews :. Cuando intenté seleccionar la anotación directamente dentro del método de delegado, ¡la llamada cayó con el pin! Eso parecía extraño, así que agrego un ligero retraso de medio segundo.

    -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { [self performSelector:@selector(selectInitialAnnotation) withObject:nil afterDelay:0.5]; }

  2. Seleccione la anotación inicial como esperaría, pero llamando a SelectAnnotation: animated;

    -(void)selectInitialAnnotation { [self.mapView selectAnnotation:self.initialAnnotation animated:YES]; }

Parece que selectAnnotation:animated: no se llama en algunas condiciones. Compare con los documentos de MKMapView :

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 efecto.


Una forma más coherente que usar un tiempo de espera fijo es escuchar la regionDidChange llamada regionDidChange . Establezca la coordenada central del mapa en la anotación deseada y, cuando se llame al método regionDidChange, seleccione la anotación en el centro para abrir la llamada.

Aquí hay un pequeño video que tomé de la cosa que se ejecuta aleatoriamente entre 5 pines.

Primero, vaya a la coordenada central de la anotación. Digamos que el objeto de anotación se llama thePin .

- (void)someMethod { [map setCenterCoordinate:thePin.coordinate animated:YES]; }

Luego, en el método regionDidChange , seleccione esta anotación.

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { [map selectAnnotation:thePin animated:YES]; }