更新用户位置或使用默认值时刷新MKMapView

koi*_*ose 6 annotations refresh mkmapview ios

我正在尝试刷新我的地图视图,并在设备获取用户位置时从服务器加载新数据.这是我正在做的事情:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

我还有一个 - (void)连接:(NSURLConnection*)连接didReceiveData:(NSData*)数据,用于创建和添加注释.

这是发生的事情:有时我会在一段时间后得到位置,所以我已经将数据加载到默认位置附近.然后我得到位置,它应该删除旧的注释并添加新的注释,而不是我一直看到旧的注释和新的注释(假设我每次都会收到10个注释,所以这意味着我有20个注释我的地图,当我应该有10).

我究竟做错了什么?

小智 0

好吧,这可能有点长,但它对我有用,我真的希望它能对你有所帮助。这是来自一个用于在驾驶员之间共享不同交通状态报告的应用程序。

我也遇到了这个问题,我尝试从服务器加载注​​释,然后删除它们,并在每次用户自己向服务器发送注释/按“刷新”按钮/每 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];
    }
Run Code Online (Sandbox Code Playgroud)

请对我的答案发表评论,因为我也很乐意学习一种不太复杂的方法来解决这个问题。

我认为如果有一种方法可以在使用后台线程时“等到完成”,那么大多数此类问题都可以得到解决,因为现在发生的情况是代码在下载-解析-创建的整个过程之前继续向前运行注释加载到地图的过程实际上已经完成。