【问题标题】:How do I zoom an MKMapView to the users current location without CLLocationManager?如何在没有 CLLocationManager 的情况下将 MKMapView 缩放到用户当前位置?
【发布时间】:2011-01-29 05:51:48
【问题描述】:

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

我想在找到该位置时(以及如果它发生变化)移动并缩放到该位置。

问题是,在map 上更新用户位置时似乎没有调用任何方法,所以我无处放置zoom/scroll 的代码。

有没有办法在MKMapView 获得(或更新)用户位置时收到通知,以便我可以移动/缩放到它?如果我使用自己的CLLocationManager,我得到的更新与地图上用户标记的更新不对应,所以当我的地图在蓝色图钉出现前几秒钟移动和缩放时,它看起来很傻。

这感觉像是基本功能,但我花了数周时间寻找解决方案,但没有找到任何接近的解决方案。

【问题讨论】:

  • 我已经添加了一个 CLLocationManager 来手动执行此操作,但它甚至不会在 MapView 绘制用户位置的同时触发,所以它看起来很糟糕。我不明白为什么这会这么难做

标签: iphone mkmapview


【解决方案1】:

从 iOS 5.0 开始,Apple 为 MKMapView 添加了一个新方法。此方法完全符合您的要求,甚至更多。

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

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

【讨论】:

  • 不错的收获。这要容易得多。
  • 完美!为我节省了大量时间。谢谢!!
  • 这应该是 iOS 5 及更高版本的公认答案。一行代码:[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
【解决方案2】:

试试这个:

[mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];

【讨论】:

    【解决方案3】:

    您必须注册MKMapViewuserLocation.location 属性的KVO 通知。

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

    [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。

    【讨论】:

    • 我以前从未使用过 KVO,所以不得不谷歌。看起来这正是我需要的 - 谢谢!
    • 这段代码有问题。仅当用户位置已经在地图上可见的某个位置时才有效。 [self.mapView isUserLocationVisible] 仅当用户位置在当前地图区域内时为真。相反,该行应为:self.mapView.showsUserLocation
    • @Felix 对我来说似乎不是这样
    • 对于那些对如何实现感到困惑的人:[self moveOrZoomOrAnythingElse];只需在此链接中添加类别:troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview 到您的代码中,然后替换行:[self moveOrZoomOrAnythingElse]; with [self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:14 animated:YES];它就像一个魅力。
    • 感谢您的精彩回答...顺便说一句,那些努力让它工作的人,您必须设置“mapView.showsUserLocation = YES;”否则这将不起作用。
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      这是对我有用的 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 组合。 viewDidLoad 可以在 dealloc 发生多次之前调用 - 第一次发生时,应用程序崩溃。
      【解决方案6】:

      没问题...在具有 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
      

      【讨论】:

      • 我尝试了很多,但问题似乎是此代码运行之前用户位置已确定。
      猜你喜欢
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 2011-12-04
      • 2011-08-29
      • 2015-05-22
      • 2017-05-02
      • 2011-08-11
      • 2020-01-01
      相关资源
      最近更新 更多