我有一个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
。
答案 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
是负责通过更新调用调用委托的对象。如果您检查showsUserLocation
和mapView.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,这里是调用序列:
mapView.delegate = self
然而,这是调用序列应该如何:
mapView.delegate = self
mapView.showsUserLocation = true
这改变了一切。有时不会立即放大mapView,有时几秒钟后,mapView会立即放大,当屏幕打开时,会调用didUpdateUserLocation / web服务。
现在更多关于为什么,它仍然&#34;有时&#34;工作。这只是因为我的iPhone的位置有时会在地图屏幕加载后立即更新,有时不会:-)。我不得不说除了上面提到的stackoverflow帖子之外,还有什么帮助我在模拟器中测试我的应用程序,因为我需要使用具有明显静态位置坐标的gpx文件,我描述的不可预测的行为然后是系统的。
因此,尽管我喜欢Interface Builder,但我可能不得不重新考虑爱是无条件的。
PS:我知道这篇文章已经过时了,我的答案与@Patrick Perini的问题并不完全相关,但是我希望它对其他人有所帮助,并且它可能会回答@Patrick Perini关于Bug是一个事实的结论如果不是,那就是错。感谢您阅读此博文: - )