Обновление MKMapView при обновлении местоположения пользователя или использовании значений по умолчанию - PullRequest
6 голосов
/ 30 апреля 2011

Я пытаюсь обновить вид карты и загрузить новые данные с сервера, когда устройство получает местоположение пользователя. Вот что я делаю:

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

У меня также есть - (void) соединение: (NSURLConnection *) соединение didReceiveData: (NSData *) данные для создания и добавления аннотаций.

Вот что происходит: иногда я получаю местоположение через некоторое время, поэтому я уже загрузил данные близко к местоположению по умолчанию. Затем я получаю местоположение, и оно должно удалить старые аннотации и добавить новые, вместо этого я продолжаю видеть старые аннотации, а новые все равно добавляются (скажем, я получаю 10 аннотаций каждый раз, поэтому означает, что у меня на карте 20, а у меня 10).

Что я делаю не так?

1 Ответ

0 голосов
/ 27 ноября 2011

Хорошо, это может быть немного долго, но это сработало для меня, и я действительно надеюсь, что это поможет вам.Это из приложения, которое используется для обмена различными отчетами о состоянии трафика между драйверами.

У меня также была эта проблема, я пытался загрузить аннотации с сервера, затем удалить их и перезагрузить массив аннотаций на карту каждый развремя, когда пользователь сам отправляет аннотацию на сервер / нажимает кнопку «обновить» / каждые 1,5 минуты, чтобы у него всегда был текущий набор.

Так что я подумал, что это может быть связано со временеминтервал, который требуется для загрузки новых аннотаций с сервера или с самим массивом, позже я понял, что это также может быть связано с тем, как весь код был организован, и что, возможно, некоторые вещи просто мешают другим.

В основном я перемещал команду [self.map addAnnotations:AN ARRAY OF ANNOTATIONS] в основной поток и весь процесс загрузки назад. Я также использовал временный массив вместо «self.map.annotations» для удаления текущих аннотаций., потом все работало нормально, так что я просто оставил это так :), хотя я не мир-сэксперт (даже не близко), и я уверен, что у других может быть более профессиональное и эффективное решение, пример кода:

//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];
    }

Пожалуйста, прокомментируйте мой ответ, так как я также буду очень рад узнатьменее сложный способ решения этого вопроса.

Я думаю, что большинство проблем такого типа были бы решены, если бы существовал способ «подождать, пока не будет сделано» при использовании фоновых потоков, потому что теперь происходит то, что кодпродолжает работать до того, как весь процесс загрузки-анализа-создания-загрузки аннотаций на карту будет фактически завершен.

...