2011-10-27 11 views
8

Ho una vista modale nella mia app che visualizza un UIMapView. Aggiungo quindi un gran numero di annotazioni (oltre 800) a questa vista mappa (codice sotto).Codice di ottimizzazione per MKMapView - Numero elevato di annotazioni

Il problema è che l'utente è costretto ad attendere un minuto circa mentre tutti i pin vengono caricati. Anche l'app diventa pigra una volta che tutti gli 800 pin sono sulla mappa.

Qualcuno può suggerire come posso migliorare il mio codice qui sotto?

Grazie.

#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; 
} 

risposta

10

I due più grandi miglioramenti di velocità si possono fare qui sono:

  • Implementare vista annotazione riutilizzo (in questo momento crea una nuova vista ogni volta che ha bisogno di mostrare un'annotazione, anche se lo stesso
  • Modificare come è impostato il UniqueID. Per impostarlo, il codice sta attualmente eseguendo il ciclo di tutte le annotazioni ogni volta che crea una vista di annotazione (che potrebbe accadere in qualsiasi momento in cui la vista della mappa viene ingrandita o ingrandita- -non solo la volta iniziale)

In primo luogo, invece di cercare la UniqueID nel metodo viewForAnnotation e utilizzando un tag pulsante per passare l'identificatore di annotazione, aggiungere UniqueID come una proprietà per la vostra abitudine di classe di annotazioneMyLocation e impostare la proprietà quando si aggiunge l'annotazione se stesso in addPins:

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

Si potrebbe anche aggiungere uniqueID come parametro al metodo initWithName invece di assegnare la proprietà a parte.


successivo, per attuare l'annotazione vista riutilizzo, il metodo viewForAnnotation dovrebbe essere simile:

- (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; 
} 


Infine, per rispondere al pulsante e capire che UniqueID mostrare dettaglio per, implementare il metodo calloutAccessoryControlTapped delegato:

- (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... 
} 


Dopo tutte queste modifiche, solo il caricamento iniziale delle annotazioni occuperà la maggior parte del tempo. Se questo è ancora un problema, una soluzione è aggiungere solo annotazioni che sarebbero visibili nell'area attualmente visualizzata e aggiungere/rimuovere annotazioni quando l'utente cambia la regione visibile.

4

Sono completamente d'accordo con Anna. Ma considera che 800 AnnotationViews allo stesso tempo si tradurrà in un'interfaccia estremamente lenta. Pertanto, se la tua mappa deve fornire l'interazione dell'utente come lo scorrimento o lo zoom, è meglio implementare un raggruppamento gentile delle tue viste di annotazione.

Problemi correlati