在没有CLLocationManager的情况下如何将MKMapView缩放到用户的当前位置?


70

使用时,MKMapView有一个名为“显示用户当前位置”的选项,它将自动在上显示用户位置map

找到位置后(如果更改),我想移动并缩放到该位置。

问题是,在上更新用户位置时,似乎没有任何方法被调用map,因此我无处可放将要发布的代码zoom/scroll

MKMapView某人获得(或更新)了用户位置后,是否有一种方法可以通知我,以便我可以将其移动/缩放到该位置?如果我使用自己CLLocationManager的更新,则我得到的更新与地图上用户标记的更新不对应,因此当我的地图移动并缩放到出现蓝色图钉之前几秒钟时,它看起来很傻。

感觉像是基本功能,但是我花了数周时间寻找解决方案,但没有关闭任何东西。


我添加了一个CLLocationManager来手动执行此操作,但是在MapView绘制用户位置时,它甚至不会同时触发,因此看起来很麻烦。我不明白为什么这样做会如此困难
Danny Tuppeny

Answers:


106

您必须注册的userLocation.location属性的KVO通知MKMapView

为此,请将此代码放入viewDidLoad:ViewController或初始化地图视图的任何位置。

[self.mapView.userLocation addObserver:self  
        forKeyPath:@"location"  
           options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)  
           context:NULL];

然后实现此方法以接收KVO通知

- (void)observeValueForKeyPath:(NSString *)keyPath  
                      ofObject:(id)object  
                        change:(NSDictionary *)change  
                       context:(void *)context {  

    if ([self.mapView showsUserLocation]) {  
        [self moveOrZoomOrAnythingElse];
        // and of course you can use here old and new location values
    }
}

这段代码对我来说很好用。
顺便说一句,self在这种情况下是我的ViewController。


1
我以前从未使用过KVO,所以只用过Google。看起来这完全可以满足我的需求-谢谢!
Danny Tuppeny 2010年

6
这段代码有问题。仅当用户位置已经在地图上可见位置上时,它才起作用。[self.mapView isUserLocationVisible]仅在用户位置在当前地图区域内时才为true。相反,该行应显示为:self.mapView.showsUserLocation
Felix Lamouroux 2010年

@Felix对我而言似乎并非如此
D-Nice 2010年

12
对于那些对如何实现感到困惑的人:[self moveOrZoomOrAnythingElse]; 只需在以下链接中添加类别:troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview 至您的代码,然后替换以下行:[self moveOrZoomOrAnythingElse]; 与[self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:14 animation:YES]一起使用;它像一种魅力。
Vibhor Goyal,2010年

感谢您的出色回答...顺便说一句,那些想让它正常工作的人必须设置“ mapView.showsUserLocation = YES;”。否则,这将无法正常工作。
2013年

52

这是ddnv和达斯汀的答案的结合,对我有用:

mapView是MKMapView * mapView的名称;

在viewDidLoad中添加此行,请注意加载中可能会有更多行。这只是简化了。

- (void) viewDidLoad
{
    [self.mapView.userLocation addObserver:self 
                                forKeyPath:@"location" 
                                   options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
                                   context:nil];
}

然后创建将地图移动到当前位置的实际列表方法:

// Listen to change in the userLocation
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{       
    MKCoordinateRegion region;
    region.center = self.mapView.userLocation.coordinate;  

    MKCoordinateSpan span; 
    span.latitudeDelta  = 1; // Change these values to change the zoom
    span.longitudeDelta = 1; 
    region.span = span;

    [self.mapView setRegion:region animated:YES];
}

不要忘记适当地分配并注销观察者:

- (void)dealloc 
{
    [self.mapView.userLocation removeObserver:self forKeyPath:@"location"];
    [self.mapView removeFromSuperview]; // release crashes app
    self.mapView = nil;
    [super dealloc];
}

不正确-您可以执行init / dealloc或viewDidLoad / viewDidUnload组合。可以在多次发生dealloc之前调用viewDidLoad-这是第一次发生,应用崩溃。
joshis 2012年

46

自iOS 5.0以来,Apple已向MKMapView添加了新方法。此方法完全可以满足您的需求。

看看:https : //developer.apple.com/documentation/mapkit/mkmapview

- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;

6
不错的收获。这非常容易。
克里斯·纳德勒

完善!节省了我很多时间。谢谢!!
tg2

1
从iOS 5起,这应该是公认的答案。一行代码:[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
Scott Heaberlin 2014年

13

您可以MKMapView通过实施MKMapViewDelegate协议来监视何时更新地图上的用户位置。只需实施:

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

此回调应与地图上显示的内容完全同步。



1

没问题...在具有MKMapView的UIViewController子类的viewDidLoad方法中,将其添加(假设您的MKMapView命名为map):

CLLocation *location = [[[CLLocation alloc] initWithLatitude:map.centerCoordinate.latitude longitude:map.centerCoordinate.longitude] autorelease]; //Get your location and create a CLLocation
MKCoordinateRegion region; //create a region.  No this is not a pointer
region.center = location.coordinate;  // set the region center to your current location
MKCoordinateSpan span; // create a range of your view
span.latitudeDelta = BASE_RADIUS / 3;  // span dimensions.  I have BASE_RADIUS defined as 0.0144927536 which is equivalent to 1 mile
span.longitudeDelta = BASE_RADIUS / 3;  // span dimensions
region.span = span; // Set the region's span to the new span.
[map setRegion:region animated:YES]; // to set the map to the newly created region

3
我做了很多尝试,但是问题似乎是这段代码确定用户位置之前运行。
Danny Tuppeny 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.