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

发布于 2024-11-04 22:20:27 字数 2140 浏览 1 评论 0原文

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

- (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)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data,用于创建和添加注释。

发生的情况如下: 有时我会在一段时间后获得位置,所以我已经加载了接近默认位置的数据。 然后我获取位置,它应该删除旧注释并添加新注释,但我总是看到旧注释并添加新注释(假设我每次收到 10 个注释,所以这意味着我的地图上应该有 10 个,但我却有 20 个)。

我做错了什么?

I'm trying to refresh my map view and load new data from the server when the device acquires the user location.
Here's what I'm doing:

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

I also have a - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data, to create and add the annotations.

Here's what happens:
sometimes I get the location after a while, so I already loaded data close to the default location.
Then I get the location and it should remove the old annotations and add the new ones, instead I keep seeing the old annotations and the new ones are added anyway (let's say I receive 10 annotations each time, so it means that I have 20 on my map when I should have 10).

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

握住我的手 2024-11-11 22:20:32

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

我也遇到了这个问题,我尝试从服务器加载注​​释,然后删除它们,并在每次用户自己向服务器发送注释/按“刷新”按钮/每 1.5 分钟时将注释数组重新加载到地图 - 所以他将永远拥有当前的一套。

所以我认为这可能与从服务器加载新注释所需的时间间隔有关,或者与数组本身有关,后来我意识到它也可能与整个代码的组织方式有关,也许有些事情只是妨碍了其他人/时机。

我所做的基本上是将 [self.map addAnnotations:AN ARRAY OF ANNOTATIONS] 命令移动到主线程,并将整个加载过程移到后面,我还使用了一个临时数组而不是“self.map”。 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];
    }

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

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

Ok this might be a little long but it worked for me and I really do hope it will help you.
This is from an app that is used to share different traffic status reports between drivers.

I had this problem also, I tried to load annotations from a server, then delete them and reload the annotations array to the map every time the user sends an annotation to the server himself/presses the "refresh" button/every 1.5 minutes - so that he will always have the current set.

So I thought it might have something to do with the time interval that it takes to load the new annotations from the server, or with the array itself, later I realized it might also be connected to the way the entire code was organized and that maybe some things just got in the way/timing of others.

What I did is basically moving the [self.map addAnnotations:AN ARRAY OF ANNOTATIONS] command to the main thread and the whole loading process to the back, I also used a temp array instead of "self.map.annotations" to delete the current annotations, it worked ok afterwards so I just left it like that :), though I'm not a world-class expert (not even close) and I'm sure others might have a more professional and efficient solution, code sample:

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

Please do comment on my answer since I will also be very happy to learn a less complicated way of solving this matter.

I think most of these type of problems would have been solved if there was a way to "wait until done" when using background threads, because now what happens is that the code continues to run forward before the whole process of downloading-parsing-creating annotation-loading to map process is actually finished.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文