当userLocation的视图是自定义时,不会调用didUpdateUserLocation

时间:2012-11-11 17:00:24

标签: ios geolocation mkmapview mapkit mkmapviewdelegate

我有一个MKMapView,它应该使用自定义视图(不是蓝点)跟踪用户的位置。为了将这个视图替换为蓝点,我将其归还:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (annotation == [mapView userLocation])
    {
        return userLocationView;
    }
}

要初始化跟踪,请致电

[mapView setShowsUserLocation: YES];
[mapView setUserTrackingMode: MKUserTrackingModeFollow animated: NO];
[mapView setDelegate: self];

正如预期的那样,当应用加载时,-mapView:didUpdateUserLocation:会被调用一次。不幸的是,除非我将-mapView:viewForAnnotation:更改为具有以下实现,否则永远不会再次调用它:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (annotation == [mapView userLocation])
    {
        return nil;
    }
}

通过这些更改,地图会加载蓝点作为用户位置的指示符,并且-mapView:didUpdateUserLocation:会被频繁调用,如预期的那样。

是否存在某种互斥性以跟踪用户的位置并拥有自定义用户位置视图?我怎么能让两者都发生?

来源

此项目演示了此问题。 https://dl.dropbox.com/u/2338382/MapKitFuckery.zip

错误

这很可能是一个错误,我已将其作为雷达提交。在此期间,接受的答案应该证明是充分的。但是,值得注意的是,我必须完全放弃[mapView userLocation][mapView showsUserLocation],而只支持自定义注释和CLLocationManager

2 个答案:

答案 0 :(得分:11)

不是依赖地图视图的位置更新,而是启动CLLocationManager,设置其delegate并等待-locationManager:didUpdateToLocation:fromLocation:(在iOS 5及更低版本中)或-locationManager:didUpdateLocations:( iOS 6)。与使用地图视图的委托方法相比,您将获得更可靠,更丰富的信息。你可能知道这样做的方法,但它是:

#import <CoreLocation/CoreLocation.h>

- (void)viewWillAppear:(BOOL)animated
{
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager startUpdatingLocation];
}

// Deprecated in iOS 6
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{

    // Check the age of the newLocation isn't too long ago using newLocation.timestamp

    // Set the map dot using newLocation.coordinate

    // Set an MKCircle to represent accuracy using newLocation.horizontalAccuracy
}

我查看了进入mapView委托的委托调用,并返回nil以外的任何内容,停止对-mapView:didUpdateUserLocation:的调用,就像你说的那样。以下是他们到达顺序的电话:

 - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView
 - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id < MKAnnotation >)annotation
 - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView
 - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error

据推测,MKUserLocation对象,而不是MKMapView是负责通过更新调用调用委托的对象。如果您检查showsUserLocationmapView.userLocation的状态,它们看起来都很好:

NSLog(@"%d %@", mapView.showsUserLocation, mapView.userLocation);

返回1和非零对象(1 <MKUserLocation: 0x1e02e580>)。也许mapView查询其userLocation对象以获取当前位置,然后将其发送给委托。如果该对象消失了,它将无法工作。

这有点奇怪,但就像我说的那样,你会从CLLocationManager的更新中获得更好的更新。

答案 1 :(得分:1)

一个古老的问题,我想以自己的方式回答。我有一个类似的问题。我只需要进行Web服务调用,将用户位置作为GET参数传递,当我加载MapView的ViewController / Screen并通过mapView检索用户位置时。然后在委托方法didUpdateUserLocation中调用Web服务是有意义的。我没有注意到错误的行为,因为事情似乎工作正常,但由于某些原因,有时在打开mapView屏幕时,用户蓝点会显示但是地图不会放大&#34;放大&#34;既没有调用过UUateUserLocation,也没有调用我的内部Web服务。在盯着屏幕几秒钟后,地图会放大&#34;放大&#34;并调用了didUpdateUserLocation / web服务。我想过一些小故障,不是什么大不了的事。现在,我的注重细节的开发人员仍然感到沮丧,经过几周的思考,我决定对此采取行动。 Stackoverflow并没有立即给出答案,但我指出了正确的方向。这是罪魁祸首:通话顺序!疯狂,但一旦我弄清楚事情就完全有道理。我知道为了看到蓝点并获得用户位置,我必须告诉mapView这样做。因此,作为一名Interface Builder爱好者,我为IB中的mapView正确设置,即我选中了框:&#34;用户位置&#34;,简单。然后仔细阅读mapView文档,我意识到我的ViewController需要符合MKMapViewDelegate,完成交易。正如我所说的那样,事情似乎工作正常,蓝点会立即显示,但有时会放大&#34;放大&#34;地图需要几秒钟......我的iPhone已经有3年了,事情变得越来越慢,我处理的是迟缓......然后我读了这个堆栈溢出帖子(https://stackoverflow.com/a/37407955 )事情变得清晰了。就我而言,由于使用IB,这里是调用序列:

  1. 在IB
  2. 中选中的用户位置复选框
  3. 在viewDidLoad中,请致电:mapView.delegate = self
  4. 然而,这是调用序列应该如何:

    1. 用户位置复选框未在IB中签入(这很重要)
    2. mapView.delegate = self
    3. mapView.showsUserLocation = true
    4. 这改变了一切。有时不会立即放大mapView,有时几秒钟后,mapView会立即放大,当屏幕打开时,会调用didUpdateUserLocation / web服务。

      现在更多关于为什么,它仍然&#34;有时&#34;工作。这只是因为我的iPhone的位置有时会在地图屏幕加载后立即更新,有时不会:-)。我不得不说除了上面提到的stackoverflow帖子之外,还有什么帮助我在模拟器中测试我的应用程序,因为我需要使用具有明显静态位置坐标的gpx文件,我描述的不可预测的行为然后是系统的。

      因此,尽管我喜欢Interface Builder,但我可能不得不重新考虑爱是无条件的。

      PS:我知道这篇文章已经过时了,我的答案与@Patrick Perini的问题并不完全相关,但是我希望它对其他人有所帮助,并且它可能会回答@Patrick Perini关于Bug是一个事实的结论如果不是,那就是错。感谢您阅读此博文: - )