2009-08-10 23 views
29

Después de llamar MKMapView 's setCenterCoordinate: animada: método (sin animación), me gustaría llamar selectAnnotation: animada: (con animación) por lo que la anotación sale de la chinche recientemente centrada.Se busca: Cómo fiable, consistente seleccionar una anotación MKMapView

Por ahora, simplemente miro para 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 está seleccionada. :(

Muy bien. Podría llamar 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 ha terminado de cargarse). 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 una cuestión de saber si mi coordenada es visible, ya que es posible perder casi una pantalla de distancia y tener que cargar nuevos datos del mapa. Por el contrario, es cuestión de saber si es necesario cargar nuevos datos de mapas y luego actuar en consecuencia.

Cualquier ideas sobre cómo lograr esto, o cómo lo contrario (fiable) seleccionar una anotación después de volver a centrar la vista del mapa en la coordenada donde esa anotación vidas?

Pistas apreciadas - gracias!

Respuesta

36

me encontré con el mismo problema, pero no encontraron lo que parece ser una solución fiable 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 agregué 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 era de esperar, pero selectAnnotation llamando: animada;

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

Parece que selectAnnotation:animated: no se llama en algunas condiciones. Comparar con MKMapView docs:

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

+0

¡Así que todo se trata del tiempo! Muchas gracias por compartir esto. Lo probaré. –

+0

Parece que funciona, mejor que esperar a que se cargue el mapa, si es así. en una conexión lenta, son muchas las edades antes de que se muestre la anotación. Gracias. – petert

+0

Esta es una gran respuesta. Gracias. –

0

Estaba teniendo una dificultad similar, pero en realidad no pude hacer que este método funcionara en absoluto, y mucho menos de manera inconsistente.

Esto es lo que encontré para trabajar. Tal vez va a trabajar para usted también: How to trigger MKAnnotationView's callout view without touching the pin?

+0

¡Saludos! Muchas gracias por tu respuesta. Cuando leo esto, la solución parece ser llamar * selectAnnotation: animated: * ... solo ya lo estoy intentando (ver mi descripción anterior) y no funciona. Tal vez me estoy perdiendo algo adicional? –

+0

¡Oh! Mi error. Estás hablando de la parte * que * publicaste. :) Es decir, la parte donde recorre las anotaciones y las selecciona sin animación. Lo tengo. Lo revisaré más detenidamente y veré si esto funcionaría en mi caso. ¡Gracias! –

+0

¡Está bien! Le di una oportunidad. No estoy seguro de que haga algo diferente de lo que ya estoy haciendo, que resulta ser más corto (no tan corto siempre es mejor ... pero aquí está): - (void) mapView: (MKMapView *) map selectAnnotationAtIndex: (NSInteger) index animado: (BOOL) animado { [map selectAnnotation: [[map anotaciones] objectAtIndex: index] animated: animated]; } (Para mí, animado es SÍ) Así que ya tengo una lista de anotaciones, e incluso sé el índice. El problema es que si lo llamo después de configurar la coordenada central, podría ser PRONTO. (Ver el original Q.) ¿Pensamientos? –

4

Lo que ha funcionado para mí estaba llamando selectAnnotation:animated: del método mapView:didAddAnnotationViews::

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

documentación de Apple en el mismo here.

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

+0

Exactamente. Una anotación está bien. Prueba un montón sin embargo. No es consistente. :( –

2

Estaba teniendo un problema similar. Estaba usando el MKPinAnnotationView predeterminado con animatesDrop: YES. Después añadí las anotaciones al MKMapView, yo 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 cercano. 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 truco, pero funciona. Sin embargo, no estoy seguro de si funcionará en todas las situaciones, por ejemplo en 3G vs. 3Gs. Sería mejor averiguar la función de devolución de llamada correcta para ponerlo.

selectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self 
       selector:@selector(selectClosestAnnotation) userInfo:nil 
       repeats:NO]; 

- (void)selectClosestAnnotation { 
    [mapView selectAnnotation:[mapView.annotations objectAtIndex:1] 
      animated:YES]; 
} 
+0

Brillante! Hmm, si no hay manera de saber cuándo una anotación determinada está "lista" (por ejemplo, si agregarla a la vista del mapa no es suficiente), ¡esto podría ser más una solución que un truco! pruébalo e infórmame –

7

Una manera más consistente que utilizar un tiempo de espera fijo es escuchar la devolución de 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 corriendo 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]; 
} 
+0

¡Suena natural/elegante! No puedo creer que no lo hice 't th tinta de esto antes. Lo probaré, gracias! –

+1

Esto funcionó! (Sí, finalmente llegué a intentarlo.) ¡Gracias! –

+0

¡Ja! Habló demasiado pronto.Cada vez que la región cambia, incluso moviéndolo un poco, el mapa se reorienta nuevamente, lo que lo hace un poco desorientador para el espectador. Hmm. –

1

he encontrado varios problemas con todas las soluciones que vi para mi problema (Quiero seleccionar una anotación cuando he añadido desde viewDidAppear):

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

    Esto no funcionó para mí 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 ningún efecto.

  2. Usando el método delegado mapViewDidFinishLoadingMap:.

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

Solución:

John Blackburn fue muy cerca, pero sin el método mapView:didAddAnnotationViews:.Acabo de llamar a mi propio método selectAnnotation:, antes de añadir 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 selectAnnotation: método:

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

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

+0

¡La demora hace toda la diferencia, de hecho! –

4

Bien lo digo, esto es lo que dicen los documentos,

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

Así que si quiero llamar a setCenterCoordinate:animated: o setRegion:animated: y luego quiero para seleccionar la anotación llamando, selectAnnotation:animated:, la anotación no conseguirá seleccionado y la llamada no aparecerá pd de la misma razón exacta se mencionó anteriormente en documentos, entonces la forma en que sería genial tener algo así como, setCenterCoordinate:animated:ComletionBlock pero no está allí ...! La forma en que trabajó para mí es como abajo,

[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 terminación y que u puede utilizar para seleccionar la anotación.

+0

bloques de finalización Yay! Gracias por compartir esto. :) –

Cuestiones relacionadas