2011-10-27 10 views
8

Tengo una vista modal en mi aplicación que muestra un UIMapView. Luego agrego una gran cantidad de anotaciones (más de 800) a esta vista de mapa (código a continuación).Código de optimización para MKMapView - Gran cantidad de anotaciones

El problema es que el usuario se ve obligado a esperar un minuto más o menos mientras se cargan todos los pines. Además, la aplicación se vuelve lenta una vez que todos los 800 pines están en el mapa.

¿Alguien puede sugerir cómo puedo mejorar mi código a continuación?

Gracias.

#import "MapView.h" 
#import "MapPlaceObject.h" 


@implementation MapView 
@synthesize mapViewLink, mapLocations, detail, failedLoad; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
if (self) { 
    // Custom initialization 
} 
return self; 
} 

-(void)addPins 
{ 

for (MapPlaceObject * info in mapLocations) { 


    double latitude = info.longitude; 
    double longitude = info.latitude; 

    NSString * name = info.name; 
    NSString * addressline = info.addressOne; 
    NSString * postcode = info.postCode; 

    NSString * addresscomma = [addressline stringByAppendingString:@", "]; 
    NSString * address = [addresscomma stringByAppendingString:postcode]; 

    CLLocationCoordinate2D coordinate; 
    coordinate.latitude = latitude; 
    coordinate.longitude = longitude; 
    MyLocation *annotation = [[[MyLocation alloc] initWithName:name address:address coordinate:coordinate] autorelease]; 


    [mapViewLink addAnnotation:annotation]; 

} 
} 

- (void)showLinks : (id)sender { 


if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 
    detail = [[DetailViewController alloc] initWithNibName:@"DetailViewController-iPad" bundle:nil]; 
} 

else if (!detail) { 

    NSLog(@"Detail is None"); 

    detail = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 

} 

int uniqueID = ((UIButton *)sender).tag; 

//PlaceObject *info = [mapLocations objectAtIndex:uniqueID]; 

detail.UniqueID = uniqueID; 
detail.hidesBottomBarWhenPushed = YES; 

[self.navigationController pushViewController:detail animated:YES]; 

self.detail = nil; 

[detail release]; 

} 

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{ 

if (annotation == mapView.userLocation){ 
    return nil; //default to blue dot 
}  

MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"]; 
annView.pinColor = MKPinAnnotationColorRed; 

nameSaved = annotation.title; 

for (PlaceObject * info in mapLocations) { 

    if (info.name == nameSaved) { 

     saveID = info.UniqueID; 

    } 
} 

UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
advertButton.frame = CGRectMake(0, 0, 23, 23); 
advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; 
advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 

[advertButton addTarget:self action:@selector(showLinks:) forControlEvents:UIControlEventTouchUpInside]; 

advertButton.tag = saveID; 

annView.rightCalloutAccessoryView = advertButton; 

annView.animatesDrop=TRUE; 
annView.canShowCallout = YES; 
annView.calloutOffset = CGPointMake(-5, 5); 
return annView; 

} 

- (void)dealloc 
{ 
[mapViewLink release]; 
[mapLocations release]; 
[detail release]; 
self.failedLoad = nil; 
[failedLoad release]; 
[super dealloc]; 
} 

- (void)didReceiveMemoryWarning 
{ 
// Releases the view if it doesn't have a superview. 
[super didReceiveMemoryWarning]; 

// Release any cached data, images, etc that aren't in use. 
} 

- (void)viewWillAppear:(BOOL)animated { 

if (firstTime) { 

    CLLocationCoordinate2D zoomLocation; 

    zoomLocation.latitude = 51.50801; 
    zoomLocation.longitude = -0.12789; 

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 15*METERS_PER_MILE, 15*METERS_PER_MILE); 

    MKCoordinateRegion adjustedRegion = [mapViewLink regionThatFits:viewRegion];     

    [mapViewLink setRegion:adjustedRegion animated:YES]; 

    firstTime = NO; 

}  
} 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

firstTime = YES; 

failedLoad = [[NSMutableArray alloc]init]; 

self.mapLocations = [BluePlaqueDatabase database].mapInfo; 

[self addPins]; 
} 

- (void)viewDidUnload 
{ 
[mapViewLink release]; 
mapViewLink = nil; 
[super viewDidUnload]; 
// Release any retained subviews of the main view. 
// e.g. self.myOutlet = nil; 
} 

Respuesta

10

Los dos mayores mejoras en la velocidad que puede hacer aquí son:

  • Implementar vista de anotación reutilización (en este momento se crea una nueva vista cada vez que tiene que mostrar una anotación incluso si la misma uno vuelve a aparecer
  • Cambiar cómo se establece UniqueID. Para configurarlo, el código está recorriendo actualmente todas las anotaciones cada vez que crea una vista de anotación (lo que podría suceder cada vez que se acerca o se desplaza la vista del mapa- -no solo la hora inicial).

En primer lugar, en lugar de buscar la UniqueID en el método viewForAnnotation y el uso de una etiqueta de botón para pasar el identificador de anotación, añadir UniqueID como una propiedad a su clase de anotación personalizadaMyLocation y establezca la propiedad cuando se agrega la anotación sí en addPins:

annotation.uniqueID = info.UniqueID; // <-- give id to annotation itself 
[mapViewLink addAnnotation:annotation];  

también puede añadir uniqueID como un parámetro para el método initWithName en lugar de asignar la propiedad por separado.


A continuación, para poner en práctica la anotación de vista de la reutilización, el método viewForAnnotation debería tener este aspecto:

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{ 

    if (annotation == mapView.userLocation){ 
     return nil; //default to blue dot 
    }  

    NSString *reuseId = @"StandardPin"; 
    MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId]; 
    if (annView == nil) 
    { 
     annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease]; 

     annView.pinColor = MKPinAnnotationColorRed; 
     annView.animatesDrop = YES; 
     annView.canShowCallout = YES; 
     annView.calloutOffset = CGPointMake(-5, 5); 

     UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
     advertButton.frame = CGRectMake(0, 0, 23, 23); 
     advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; 
     advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 

     annView.rightCalloutAccessoryView = advertButton; 
    } 
    else 
    { 
     //update the annotation property if view is being re-used... 
     annView.annotation = annotation; 
    } 

    return annView; 
} 


Por último, para responder al botón de prensa y averiguar qué UniqueID para mostrar el detalle para, poner en práctica el método calloutAccessoryControlTapped delegado:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
      calloutAccessoryControlTapped:(UIControl *)control 
{ 
    MyLocation *myLoc = (MyLocation *)view.annotation; 

    int uniqueID = myLoc.uniqueID; 

    NSLog(@"calloutAccessoryControlTapped, uid = %d", uniqueID); 

    //create, init, and show the detail view controller here... 
} 


Después de todos estos cambios, solo la carga inicial de las anotaciones ocupará la mayor parte del tiempo. Si eso todavía es un problema, una solución es solo agregar anotaciones que serían visibles en la región mostrada actualmente y agregar/eliminar anotaciones a medida que el usuario cambia la región visible.

4

Estoy completamente de acuerdo con Anna. Pero considere que 800 AnnotationViews al mismo tiempo resultarán en una interfaz extremadamente lenta. Por lo tanto, si su mapa debe proporcionar interacción con el usuario, como desplazarse o acercarse, mejor implementar algún tipo de agrupamiento de sus vistas de anotación.

Cuestiones relacionadas