¿Cómo se define el orden de superposición de MKAnnotationViews?

Tengo varias MKAnnotaciones (y sus vistas correspondientes) en mi mapa, y a veces se llena de gente. Ahora, las anotaciones en mi aplicación vienen en dos formas: algunas están destinadas a permanecer donde están, mientras que otras se moverán con el paso del tiempo. Prefiero tener los más estables visualmente en el fondo y los más móviles para pasar siempre delante de ellos.

Uno pensaría, tal vez, que las anotaciones agregadas más recientemente al mapa terminarían en la parte frontal (o alternativamente en la parte trasera, al menos) pero esto simplemente no parece ser la regla. Por lo que puedo decir, creo y agrego TODAS las anotaciones que no se mueven primero, y luego agrego algunas anotaciones en movimiento recién creadas, pero muchas de ellas (¡aunque no todas!) Terminan dibujadas debajo de las que permanecen en stock perpetuamente.

Curiosamente, cuando pasa el tiempo y se crean nuevas anotaciones en movimiento, tienden a gravitar más hacia la parte superior que las primeras, incluso si todos los objetos de anotación en movimiento se crearon solo después de que las partes no movidas ya se agregaron al mapa.

¿Alguien sabe un truco para alterar este extraño orden natural de las vistas de anotación en el mapa? Traté de buscar la API de Map Kit, pero no parece hablar de tal cosa.

    Ok, entonces para el método de uso de solución de MKMapViewDelegate

    - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views 

    En este método, debe reorganizar AnnotationView después de que se haya agregado a mapKit View. Entonces, el código puede verse así:

     - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { for (MKAnnotationView * annView in views) { TopBottomAnnotation * ann = (TopBottomAnnotation *) [annView annotation]; if ([ann top]) { [[annView superview] bringSubviewToFront:annView]; } else { [[annView superview] sendSubviewToBack:annView]; } } } 

    Esto funciona para mí

    Intenta configurar la zPosition de la capa de vista de anotación (annotationView.layer.zPosition) en:

     - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views; 

    En iOS 11, la implementación de displayPriority rompió todas las soluciones que usan bringSubviewToFront o zPosition .

    Si anula el CALayer de la vista de anotación, puede controlar el control de zPosition desde el sistema operativo.

     class AnnotationView: MKAnnotationView { /// Override the layer factory for this class to return a custom CALayer class override class var layerClass: AnyClass { return ZPositionableLayer.self } /// convenience accessor for setting zPosition var stickyZPosition: CGFloat { get { return (self.layer as! ZPositionableLayer).stickyZPosition } set { (self.layer as! ZPositionableLayer).stickyZPosition = newValue } } /// force the pin to the front of the z-ordering in the map view func bringViewToFront() { superview?.bringSubview(toFront: self) stickyZPosition = CGFloat(1) } /// force the pin to the back of the z-ordering in the map view func setViewToDefaultZOrder() { stickyZPosition = CGFloat(0) } } /// iOS 11 automagically manages the CALayer zPosition, which breaks manual z-ordering. /// This subclass just throws away any values which the OS sets for zPosition, and provides /// a specialized accessor for setting the zPosition private class ZPositionableLayer: CALayer { /// no-op accessor for setting the zPosition override var zPosition: CGFloat { get { return super.zPosition } set { // do nothing } } /// specialized accessor for setting the zPosition var stickyZPosition: CGFloat { get { return super.zPosition } set { super.zPosition = newValue } } } 

    Swift 3:

    Obtuve ubicaciones de pin de API y tuve problemas similares, los pines que tenían que estar en la parte superior no. Pude resolverlo así.

     var count = 0 // just so we don't get the same index in bottom pins func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) { for view in views { view.layer.zPosition = CGFloat(count) } count += 1 if count > 500 { count = 250 // just so we don't end up with 999999999999+ as a value for count, plus I have at least 30 pins that show at the same time and need to have lower Z-Index values than the top pins. } } 

    Espero que esto ayude

    Me parece que este reordenamiento de las vistas de anotación causa que la llamada emergente que aparece cuando se hace clic en una de ellas deje de estar en la parte superior de todas las anotaciones. Incluso he intentado refinarlo para que en lugar de bringSubviewToFront y sendSubviewToBack , use insertSubview:aboveSubview e insertSubview:belowSubview: donde el segundo argumento es la primera anotaciónView en la lista. Esto parecería causar mucho menos dispersión frontal a posterior, pero las llamadas salientes aún aparecen debajo de algunas anotaciones.

    Realmente necesitaba hacer esto, y ninguna de las respuestas (actuales) parecía proporcionar una implementación confiable. Trabajaron de cierta forma, pero hacer un barrido panorámico del mapa, seleccionar anotaciones o hacer un acercamiento podría volver a estropear el orden.

    La solución final y de buen comportamiento no fue tan trivial, por lo que resumiré los pasos que tomé aquí. El orden de anotación que usa MKMapView no respeta el orden agregado, o incluso el orden de una propiedad de annotations sustituida. Asi que…


    Pasos

    • Crea un CADisplayLink
    • Cada fotogtwig, reordenar anotaciones utilizando tanto la posición z de la capa como el orden de la vista en la matriz de subviews la subviews .
    • Si la vista está seleccionada, promocionela al frente en su esquema de pedido
    MKMapView tapping en las anotaciones aún respeta el orden interno de MKMapView , a pesar de los cambios ya realizados. Para contrarrestar esto, agregue un MKMapViewDelegate
    • En el método mapView:didSelect: del objeto delegado, verifica si la anotación seleccionada es la que te gustaría que fuera
    • Puede averiguar la anotación correcta / priorizada ejecutando pruebas de aciertos en las anotaciones usted mismo, teniendo en cuenta su propio orden teniendo en cuenta
    • Si la anotación seleccionada es correcta, excelente. De lo contrario, seleccione manualmente la anotación correcta utilizando selectAnnotation:animated:


    Y ahí lo tienes. El método anterior parece funcionar bien, y el rendimiento alcanzado al ejecutar este cada cuadro no es tan malo. También podría ver cambiar a MapBox, que creo que admite la ordenación de anotaciones, pero esto no siempre es una opción por varias razones.