MKMapView在启动或恢复时用户位置错误

9
当我新启动应用程序或长时间后恢复时,MKMapView对用户位置的概念是错误的,并将我显示在海中央。
我正在使用以下代码:
self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
[mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];

在应用程序或全新启动的情况下,经过漫长的简历后发生了什么......

嘿,你有没有找到这个问题的解决方案?位置在纬度为0.0和经度为0.0吗? - mbogh
我也遇到了同样的问题,但是网上关于如何解决它的信息很少。我很好奇是否有比使用最后已知位置更清晰的方法。 - Gavin Miller
7个回答

21

这是预期的行为:iPhone并不总是使用GPS跟踪用户位置(这样会消耗太多电池)。因此,一旦显示地图,MKMapView实例就会显示它所知道的最后一个“最佳”用户位置,然后通过激活跟踪来提高精度(这是一个无缝的过程,您不必担心)。

您可以通过实现MKMapViewDelegate协议来监控MKMapView何时在地图上更新用户位置,只需实现:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation      {
    CLLocationAccuracy accuracy = userLocation.location.horizontalAccuracy;
    if (accuracy ......) {
    } 
}

(更多信息请参阅苹果文档此处

我例子中的代码检查了mapView当前显示位置的准确性并相应地做出反应。

[编辑]
如果一开始在海中心显示用户位置真的让您感到困扰,您可以隐藏用户位置,直到获得足够精确/新鲜的位置。
为此,在收到足够准确的位置(通过前一个代理回调)之前,将MKMapViewshowsUserLocation属性设置为NO,然后将其设置为YES
这样做可以避免显示不准确或太旧的位置(在CLLocation中有一个timestamp属性可用于检查它是否是旧位置)

注意:您无需在您的代码中创建CLLocationManager实例,MKMapView会在内部创建一个并通过此代理选择器发布接收到的位置。


2
+1 你是第一个提到这个问题中海上观看部分的人。 - Gavin Miller

3
当直接使用CLLocationManager时,通常在第一个回调中获取到缓存的位置。虽然有些旧,但通常是一个不错的位置。之后,您会很快收到更好的位置回调,使用wifi、蜂窝塔(如果可用)。如果您要求精度小于1000m,则在更多秒钟后将获得GPS三角定位。
这些位置都不应该不准确到在海洋中间。我怀疑这行代码:
self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;

userLocationlocationnil时访问坐标。如果userLocationlocationnil,这将返回0个坐标。纬度为0,经度为0的位置位于非洲海岸外的大西洋上。在从中获取坐标之前,您可以添加一个检查location以确保它不是nil的操作:

if (self.mapView.userLocation.location) {
    self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
    [mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];           
}

您还需要等待回调到 MKMapViewDelegatemapView:didUpdateUserLocation:,以了解何时有有效位置可用。您对 didUpdateUserLocation: 的实现应丢弃任何水平精度 horizontalAccuracy < 0 的位置,这表示无效位置。
-(void)mapView:(MKMapView*)mapView didUpdateUserLocation:(MKUserLocation*)userLocation
{
    if (userLocation.location.horizontalAccuracy > 0) {
        [mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];           
    }
}

修复了地图中的中间海洋问题,谢谢! - user1832451

1

这很遗憾是GPS芯片的功能。它并不总是开启,因此数据通常在最初的几个时刻会出现错误。您最好的选择可能是将应用程序记录的最后位置存储在NSUserDefaults中,然后等待精度达到所需水平后再切换到实时数据,或者在精度达到所需水平之前隐藏MkMapView,然后在该点显示它(您可以在过渡期间显示加载屏幕)。


我该如何确保精度正确?我可以一直等到它正确,但是我该如何验证呢? - DeShawn Terrell
调用您的CLLocationManager上的(void)startUpdatingLocation,然后在您的委托中覆盖locationManager:didUpdateToLocation:fromLocation:。如果您存储了最后已知位置,则可以确定用户距其上次位置的合理距离,并显示地图。 - Jeremy Massel

1

我在这里做的是-

  1. 开始位置更新
  2. 在位置更新时,检查位置的年龄,如果太旧,我会等待
  3. 收到新的更新后,我会在地图上更新它

如果你需要非常精确的位置,那么还要检查准确性,并设置一个超过该时间无法容忍等待的超时,并使用不太准确的修复。


添加检查经纬度是否为0,这就是我解决问题的答案。 - AtomRiot

1

0

它距离您的实际位置有多远?当应用程序刚开始或从长时间暂停后恢复时,用户位置通常总是错误的。随着应用程序的运行,它将变得越来越准确。在CLLocationManager中有获取用户位置精度的方法,请查看那里获得什么样的值。


我应该在应用程序加载时等待吗?像睡眠一样? - DeShawn Terrell

0
在我的应用中,我使用了以下方法:
第一,最好有一个默认位置(例如,应用程序是关于一座城市的,则缩放以显示整个城市)(在首次应用程序打开时,当没有下载数据时);
第二,如果用户已经使用了地图,则可以存储他的坐标,并在没有其他可用数据的情况下显示这些坐标(+跨度(缩放级别))。
第三,在数据方面:
1. 如果数据库已经有一些坐标,则在第一次地图打开时(当应用程序关闭时)缩小/放大以显示地图上的所有图钉。
2. 当仍在地图中并且刚刚到达更新(新位置或更改了某些内容)时,有两种可能性:
2.1. 如果用户没有缩放到任何位置,则地图缩放/缩小以显示所有位置。
2.2. 如果用户已经缩放了进去,则位置会被更新,但地图不会缩小。
当然,还有一些筛选按钮(例如:搜索、用户位置和一些其他东西),它们会过滤位置,并缩小/放大以显示过滤结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接