2009-08-11 13 views
13

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

Parece que este problema se ha corregido en silencio en IOS 4.3. Hasta este punto, la distancia que se consideraba "lo suficientemente lejos" para que una anotación se reciclara parecía estar a cientos de millas, incluso cuando se acercaba mucho. Cuando construyo mi aplicación con iOS 4.3 SDK, las anotaciones se reciclan en función de límites más razonables.


¿Alguien más ha tenido 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 sale

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 adicional. El mapa (correctamente) solo 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 del registro para la región que está siendo configurado se imprimen 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 me está llevando a problemas de memoria.

Un posible problema es que estas anotaciones se agrupan en un espacio muy pequeño (~ radio de 1 milla). Aunque el mapa está bastante ajustado en viewDidLoad (latitud y longitud delta .001), todavía carga todas las vistas de anotación a la vez.

Gracias ...

Respuesta

14

Lo que cabe esperar es una especie de "recorte" de las vistas de anotación en base a la corriente region las pantallas de mapas.

Ésta no es la forma en que funciona selector dequeueReusableAnnotationViewWithIdentifier.

Desde su documentación: Como vistas de anotación se mueven fuera de la pantalla, la vista del mapa ellos se mueve a una cola de reutilización de administración interna. A medida que se mueven las nuevas anotaciones en la pantalla y se solicita al código que proporcione una vista de anotación correspondiente, siempre debe intentar dequear una vista existente antes de crear una nueva.

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 le caso, la forma en que iba a poner en práctica el recorte (para mostrar sólo la anotación de la región que se muestra actual) es:

  • agregar 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 bastante y el alcance de la región es demasiado grande (se muestran demasiados pines), debe tomar una decisión: ¿visualicé todas las vistas de las anotaciones? (y corro el riesgo de que mostrar en el mapa no proporciona mucha información) o configuro un mensaje para el usuario que dice "acercar para obtener alfileres" o lo que sea. Pero esta es otra historia ...;)

+0

Esta es una gran respuesta. Había leído la documentación, pero creo que me sorprendió el diseño dequeue que sonaba consistente con la eliminación de llamadas de la celda de la tabla. Con celdas de tabla, parece que limitan el tamaño de la cola y luego comienzan a liberar las celdas de la tabla (aunque no he comprobado con el depurador). Es extraño que el dequeing en el mapa no sea consistente con esto. Me pregunto por qué, cuando la lógica de mantener una lista de marcadores que están dentro y fuera de la región actual ya existe en la clase, el desarrollador debería tener que replicar esto para obtener ahorros de memoria reales. ¡¡Gracias!! – jmans

+0

Hum, sí, tienes razón, es extraño porque el nombre es realmente como el de UITableView, y como dijiste, la palabra "fuera de pantalla" permite al usuario pensar que debería funcionar como UITableView. Y tiene razón también, creo que si está creando una vista de tabla con tamaño de sección 10000, nunca obtendrá 10000 UITableViewCellView instanciado porque la mayoría de ellos se reutilizan. idea adicional: ¿cuándo configura las anotaciones en su código? ¿Estás 100% seguro de que se invoca después de establecer el valor de la región? – yonel

+0

No estoy 100% seguro, pero no tendré la oportunidad de meterme con mi código nuevamente hasta el jueves. Voy a echarle otro vistazo entonces, con tus consejos en mente, y dejarte saber lo que sucede. – jmans

0

No estoy seguro si esto ayudará, pero usted ha mencionado problemas de memoria debido a la carga de ~ 60 objetos. ¿Hay alguna forma de cargar de forma condicional cada objeto en función del centro de la región del mapa actual y el intervalo de la región del mapa actual?

// :)

+0

Bueno, idealmente eso es lo que dequeueReusableAnnotationViewWithIdentifier debería hacer, pensé. Creo que podría hacerlo desde cero y administrar una variedad de ubicaciones y cada vez que el usuario amplía o muestra, obtenga la nueva región del mapa, elimine las regiones apropiadas y luego agregue las nuevas. – jmans

Cuestiones relacionadas