2011-04-30 8 views
6

Sto tentando di aggiornare la visualizzazione della mia mappa e caricare nuovi dati dal server quando il dispositivo acquisisce la posizione dell'utente. Ecco quello che sto facendo:Aggiornamento di un MKMapView quando la posizione dell'utente viene aggiornata o utilizzando i valori predefiniti

- (void)viewDidLoad { 
    CGRect bounds = self.view.bounds; 
    mapView = [[MKMapView alloc] initWithFrame:bounds]; 
    mapView.showsUserLocation=YES; 
    mapView.delegate=self; 
    [self.view insertSubview:mapView atIndex:0]; 
    [self refreshMap]; 
} 

- (void)mapView:(MKMapView *)theMapView didUpdateUserLocation:(MKUserLocation *)userLocation 
{ 
    //this is to avoid frequent updates, I just need one position and don't need to continuously track the user's location 
    if (userLocation.location.horizontalAccuracy > self.myUserLocation.location.horizontalAccuracy) { 
     self.myUserLocation = userLocation; 
     CLLocationCoordinate2D centerCoord = { userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude }; 
     [theMapView setCenterCoordinate:centerCoord zoomLevel:10 animated:YES]; 
     [self refreshMap]; 
    } 
} 

- (void)refreshMap { 
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 
    [self.mapView removeAnnotations:self.mapView.annotations]; 
    //default position 
    NSString *lat = @"45.464161"; 
    NSString *lon = @"9.190336"; 
    if (self.myUserLocation != nil) { 
     lat = [[NSNumber numberWithDouble:myUserLocation.coordinate.latitude] stringValue]; 
     lon = [[NSNumber numberWithDouble:myUserLocation.coordinate.longitude] stringValue]; 
    } 
    NSString *url = [[NSString alloc] initWithFormat:@"http://myserver/geo_search.json?lat=%@&lon=%@", lat, lon]; 

    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url] 
cachePolicy:NSURLRequestUseProtocolCachePolicy 
timeoutInterval:60.0]; 
    [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 
    [url release]; 
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
} 

Ho anche una - connessione (void): connessione (NSURLConnection *) didReceiveData: (NSData *) i dati, per creare e aggiungere le annotazioni.

Ecco cosa succede: a volte ottengo la posizione dopo un po ', quindi ho già caricato i dati vicino alla posizione predefinita. Quindi ottengo la posizione e dovrebbe rimuovere le vecchie annotazioni e aggiungere quelle nuove, invece continuo a vedere le vecchie annotazioni e quelle nuove vengono aggiunte comunque (diciamo che ricevo 10 annotazioni ogni volta, quindi significa che io avere 20 sulla mia mappa quando dovrei avere 10).

Cosa sto sbagliando?

+0

In refreshMap, prima della riga removeAnnotations, controllare se self.mapView è nullo. – Anna

+0

Non è nulla, questo è quello che ottengo: > Non riesco nemmeno a testare correttamente perché ho notato questo problema su un dispositivo reale e non nel simulatore ... Il codice è logicamente corretto? – koichirose

+0

Non vedo alcun problema evidente. Forse è qualcosa con come vengono aggiunte le annotazioni o in viewForAnnotation. – Anna

risposta

0

Ok, questo potrebbe essere un po 'lungo ma ha funzionato per me e spero davvero che possa esserti d'aiuto. Si tratta di un'app utilizzata per condividere diversi report sullo stato del traffico tra i driver.

Ho avuto anche questo problema, ho provato a caricare annotazioni da un server, quindi cancellarle e ricaricare l'array di annotazioni sulla mappa ogni volta che l'utente invia un'annotazione al server stesso/preme il pulsante "Aggiorna"/ogni 1,5 minuti - in modo che abbia sempre il set corrente.

Quindi ho pensato che potrebbe avere qualcosa a che fare con l'intervallo di tempo che ci vuole per caricare le nuove annotazioni dal server, o con l'array stesso, in seguito ho capito che potrebbe anche essere collegato al modo in cui l'intero codice era organizzato e che forse alcune cose si sono messe in mezzo/tempi degli altri.

Quello che ho fatto è fondamentalmente spostare il comando [self.map addAnnotations:AN ARRAY OF ANNOTATIONS] sul thread principale e l'intero processo di caricamento sul retro, ho anche usato un array temporaneo invece di "self.map.annotations" per eliminare le annotazioni correnti, ha funzionato bene poi così ho appena lasciato in quel modo :), anche se non sono un esperto di livello mondiale (nemmeno vicino) e sono sicuro che altri potrebbero avere una soluzione più professionale ed efficiente, codice di esempio:

//this is in viewDidLoad, it kicks off the whole process 

    [self performSelectorInBackground:@selector(retrieveAnnotationsDataFromServer) withObject:self]; 

//this is the method for loading data 

    -(void)retrieveAnnotationsDataFromServer 
    { 
     NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init]; 
     //code for loading.. 
     NSURL *URL=[NSURL URLWithString:@"http://YOUR SERVER NAME HERE"]; 
     NSString *result=[NSString stringWithContentsOfURL:URL encoding:4 error:nil]; 
     NSLog(@"%@",result); 
     NSData *data = [NSData dataWithContentsOfURL:URL]; 
     NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; 
     [parser setDelegate:self]; 
     [parser parse]; 

    //Inside the parser delegate i take each element of the report and store it in a mutable array so that i could create the annotations later (report title, report description/subtitle, report location longitude and report location latitude) 

     [pool drain]; 
     NSLog(@"retrieveannotatinsdatafromserver pool drained"); 
    } 

    //Now, in this case the last thing that will happen before the pool is drained is that the parser`s "didEndDocument" method gonna be called, so this is where I delayed the loading like this: 

    - (void)parserDidEndDocument:(NSXMLParser *)parser 
    { 
     NSLog(@"parser - document ended, creating annotationsArray"); 
     NSLog(@"this is the size of RA Array:%d",[self.recievedTitles count]); 
     for (int i=0;i<[self.recievedTitles count];i++) 
     { 
      //RC=recieved coordinate 
      //RA=recieved annotation 
      CLLocationCoordinate2D RC; 
      RC.latitude=[[self.recievedLatitude objectAtIndex:i] doubleValue]; 
      RC.longitude=[[self.recievedLongitude objectAtIndex:i] doubleValue]; 
      if([self.recievedTitles objectAtIndex:i]==nil) 
       continue; 
      Annotation *RA=[[Annotation alloc]initWithCoordinate:RC andTitle:[self.recievedTitles objectAtIndex:i] andSubTitle:[self.recievedSubTitles objectAtIndex:i]]; 

    //the "self.AnnotationsArray" is an array i use to always hold the most current set retrieved from the server   
    [self.AnnotationsArray addObject:RA]; 
      [RA autorelease]; 
      NSLog(@"RA %d inserted",i); 
     } 
     NSLog(@"Data retrieving ended, loading annotations to map"); 
     [self performSelectorOnMainThread:@selector(addAnnotations) withObject:self waitUntilDone:NO]; 

    } 

    //this method was only defined so that i could apply it in the main thread instead of in the background like the whole loading process.. I'm sure it can be done better. 

    -(void)addAnnotations 
    { 
     [self.Map addAnnotations:self.AnnotationsArray]; 
     NSLog(@"annotations loaded to Map"); 
    } 

    //now we have retrieved them from the server for the first time, the reloading and refreshing part comes next, this method is called any time the user press refresh, sends a report to the sever, or automatically every 1.5 minutes: 

    -(void)refreshMap 
    { 
     NSArray *annotationsToDelete=[[NSArray alloc] initWithArray:self.AnnotationsArray]; 
     [self.Map removeAnnotations:annotationsToDelete]; 
     [annotationsToDelete release]; 
     [self performSelectorInBackground:@selector(retrieveAnnotationsDataFromServer) withObject:self]; 
    } 

Per favore, commentate la mia risposta, poiché sarò anche molto felice di apprendere un modo meno complicato per risolvere questo problema.

penso la maggior parte di questo tipo di problemi sarebbe stato risolto se ci fosse un modo per "aspettare fino al fatto" quando si usa thread in background, perché ora ciò che accade è che il codice continua a correre in avanti prima che l'intero processo di download -parsing-creating annotation-loading per mappare il processo è in realtà finito.

Problemi correlati