Ios 当userLocation的视图为custom时未调用didUpdateUserLocation

Ios 当userLocation的视图为custom时未调用didUpdateUserLocation,ios,geolocation,mkmapview,mapkit,mkmapviewdelegate,Ios,Geolocation,Mkmapview,Mapkit,Mkmapviewdelegate,我有一个MKMapView,它应该使用自定义视图(而不是蓝点)来跟踪用户的位置。为了将此视图替换为蓝点,我将其返回: - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if (annotation == [mapView userLocation]) { return userLocationView;

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

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (annotation == [mapView userLocation])
    {
        return userLocationView;
    }
}
正如所料,
-mapView:didUpdateUserLocation:
在应用程序加载时被调用一次。不幸的是,除非我将
-mapView:viewForAnnotation:
更改为具有以下实现,否则不会再次调用它:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (annotation == [mapView userLocation])
    {
        return nil;
    }
}
-(MKAnnotationView*)地图视图:(MKMapView*)地图视图注释:(id)注释
{
如果(注释==[mapView用户位置])
{
返回零;
}
}
通过这些更改,地图将加载蓝点作为用户位置的指示器,并且像预期的那样频繁调用
-mapView:didUpdateUserLocation:

跟踪用户的位置和自定义用户位置视图是否存在某种相互排他性?我怎样才能做到这两个呢

来源 这个项目演示了这个问题

缺陷
这很可能是一个bug,我把它作为雷达归档了。在此期间,被接受的答案应该足够了。但是,值得注意的是,我不得不完全放弃
[mapView userLocation]
[mapView showsUserLocation]
,而只支持自定义注释和
CLLocationManager

而不是依赖地图视图的位置更新,启动
CLLocationManager
,设置其
委托
并等待
-locationManager:DidUpdateLocation: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
}
大概是
MKUserLocation
对象,而不是
MKMapView
是负责通过更新调用调用委托的对象。如果检查
showsUserLocation
mapView.userLocation
的状态,它们看起来都很好:

NSLog(@"%d %@", mapView.showsUserLocation, mapView.userLocation);
返回
1
和非nil对象(
1
)。可能
mapView
查询其
userLocation
对象以获取当前位置,然后将其发送给代理。如果那个物体不见了,它就不工作了


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

这是一个老问题,我想用我自己的方式回答。我有一个类似的问题。我只需要在MapView的ViewController/Screen加载并由MapView检索用户位置时进行web服务调用,将用户位置作为GET参数传递。然后在委托方法didUpdateUserLocation中调用web服务是有意义的。首先,我没有注意到错误的行为,因为事情似乎运行正常,但由于某些原因,有时在打开mapView屏幕时,会显示用户蓝点,但地图不会“放大”,并且没有调用didUpdateUserLocation,也没有调用我的内部web服务调用。盯着屏幕看几秒钟后,地图就会“放大”,并调用didUpdateUserLocation/web服务。我想是个小故障,没什么大不了的。现在,我面向细节的开发人员的头脑仍然很沮丧,经过几周的思考,我决定对此采取行动。Stackoverflow没有马上给我答案,但还是为我指明了正确的方向。罪魁祸首就在这里:一连串的呼叫!让人发狂,但一旦我弄明白了一切就完全有意义了。我知道为了看到蓝点并获得用户位置,我必须告诉mapView这样做。因此,作为一名界面构建者爱好者,我在IB中为我的mapView正确地设置了东西,也就是说,我选中了“用户位置”框,很简单。然后仔细阅读mapView文档,我意识到我的ViewController需要符合MKMapViewDelegate,done deal。正如我所说,事情似乎进展顺利,蓝点会立即显示出来,但有时地图的“放大”需要几秒钟。。。嗯,我的iPhone已经3年了,速度越来越慢,我会处理缓慢的问题。。。然后我读了这篇堆栈溢出文章(),事情就清楚了。在我的例子中,由于使用IB,调用顺序如下:

  • 在IB中选中用户位置复选框
  • 在viewDidLoad中,调用:
    mapView.delegate=self
  • 鉴于,以下是调用顺序:

  • IB中未选中用户位置复选框(这很重要)
  • mapView.delegate=self
  • mapView.showsUserLocation=true
  • 这改变了一切。现在,当屏幕打开时,地图视图会立即放大,并调用didUpdateUserLocation/web服务,而不是让地图视图有时会立即放大,有时会在几秒钟后放大

    现在再解释一下为什么,它仍然“有时”起作用。这仅仅是因为我的iPhone的位置有时会在地图屏幕加载后立即更新,有时则不更新:-)。我不得不说,除了我上面提到的stackoverflow帖子之外,帮助我的还有在模拟器中测试我的应用程序,因为我需要使用带有明显静态位置坐标的gpx文件,我描述的不可预测行为是系统性的

    所以,尽管我非常喜欢界面生成器,但我可能不得不重新考虑这种爱是多么无条件


    PS:我知道这篇文章很老,我的答案与@Patrick Perini的问题并不完全相关,但我希望它能帮助其他人,并且它可能会回答@Patrick Perini的结论,即一个错误是错误的,而不是错误。感谢您阅读本文:-)

    我最终放弃了使用用户跟踪,转而使用自定义注释视图dr
     - (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
    
    NSLog(@"%d %@", mapView.showsUserLocation, mapView.userLocation);