MKMapView cargar todas las vistas de anotación a la vez (incluyendo los que están fuera de la rect actual)

StackOverflow https://stackoverflow.com/questions/1262742

Pregunta

Actualizar

Parece que este problema se ha corregido en silencio en IOS 4.3. Hasta este punto, la distancia que se considera "lo suficiente" para una anotación para ser reciclados parecía ser cientos de miles, incluso cuando se acerca muy de cerca. Cuando construyo mi aplicación con el SDK de iOS 4.3, las anotaciones se reciclan basan en límites más razonables.


Alguien más con este problema? Aquí está el código:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(WWMapAnnotation *)annotation {



// Only return an Annotation view for the placemarks. Ignore for the current location--the iPhone SDK will place a blue ball there.

NSLog(@"Request for annotation view");

if ([annotation isKindOfClass:[WWMapAnnotation class]]){



    MKPinAnnotationView *browse_map_annot_view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"BrowseMapAnnot"];



    if (!browse_map_annot_view) {
        browse_map_annot_view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"BrowseMapAnnot"] autorelease];
        NSLog(@"Creating new annotation view");
    } else {
        NSLog(@"Recycling annotation view");
        browse_map_annot_view.annotation = annotation;
    }

...

Tan pronto como aparece la vista, me

2009-08-05 13:12:03.332 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Request for annotation view
2009-08-05 13:12:03.333 xxx[24308:20b] Creating new annotation view

y así sucesivamente, para cada anotación (~ 60) He añadido. El mapa (correctamente) sólo muestra las dos anotaciones en el rect actual. Me he fijado en la región viewDidLoad:

if (center_point.latitude == 0) {
    center_point.latitude = 35.785098;
    center_point.longitude = -78.669899;
}

if (map_span.latitudeDelta == 0) {
    map_span.latitudeDelta = .001;
    map_span.longitudeDelta = .001;
}

map_region.center = center_point;
map_region.span = map_span;

NSLog(@"Setting initial map center and region");

[browse_map_view setRegion:map_region animated:NO];

La entrada de registro para la región de ser conjunto se imprime en la consola antes de solicitar los puntos de vista de anotación.

El problema aquí es que, dado que todas las anotaciones se están solicitando a la vez, [MAPview dequeueReusableAnnotationViewWithIdentifier] no hace nada, ya que hay MKAnnotationViews únicas para cada anotación en el mapa. Esto está dando lugar a problemas de memoria para mí.

Un posible problema es que estas anotaciones se agrupan en un espacio muy pequeño (~ radio de 1 milla). Aunque el zoom es bastante ajustado en viewDidLoad (latitud y longitud delta 0.001), todavía carga todos los puntos de vista de anotación a la vez.

Gracias ...

¿Fue útil?

Solución

Lo que cabe esperar es una especie de "recorte" de las vistas de anotación basado en el actual region las pantallas de mapas.

Esto no es la forma en que funciona el selector dequeueReusableAnnotationViewWithIdentifier.

A partir de la documentación: Como vistas de anotación se mueven fuera de la pantalla , la vista del mapa que se mueve a una cola de reutilización de administración interna. Como nuevas anotaciones se mueven en pantalla, y su código se solicita para proporcionar una vista de anotación correspondiente, siempre se debe intentar quitar de la cola de una vista existente antes de crear uno nuevo.

Así que el mecanismo reutilizable sólo tiene sentido cuando se invoca una secuencia como:

//this will create 1000 annotation views
[theMap addAnnotations:my1000annotations];
//this will move them offscreen (but some annotation views may be kept internally for further reuse)
[theMap removeAnnotatios:theMap.annotations];
//when adding back again some annotations onscreen, some of the previous annotation views will be reused.
[theMap addAnnotations:someNew400annotations];

En caso de que, como me gustaría poner en práctica el recorte (que sólo se muestre la anotación de la región que se muestra actual) es:

  • Añadir un delegado a su MAPview y poner en práctica el método - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated estar informado cuando la región ha cambiado
  • iterar a través de todos sus objetos para conseguir los que coinciden con esta región
  • addAnnotations a su mapa sólo para aquellos objetos (se puede poner en práctica una especie de fusión entre las anotaciones que se mostró anteriormente y el nuevo o simplemente reiniciar desde cero, eliminar todas las anotaciones, y establecer los nuevos

Por supuesto, cuando el usuario se aleja mucho y que el ámbito de la región es demasiado grande (demasiados alfileres para ser mostradas), entonces usted tiene que tomar una decisión: ¿Debo exhibidas todos los puntos de vista de anotaciones (y correr el riesgo de que la pantalla en el mapa no da mucha información) o puedo configurar un mensaje al usuario diciendo "acercar la imagen para obtener pasadores" o lo que sea. Pero esta es otra historia ...;)

Otros consejos

No estoy seguro si esto ayudará, pero usted ha mencionado problemas de memoria debido a la carga de ~ 60 objetos. ¿Hay una manera de cargar condicionalmente cada objeto basado en el centro del mapa región actual y la duración de mapa de la región actual?

//:)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top