Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I zoom an MKMapView to the users current location without CLLocationManager?

With the MKMapView there's an option called "Show users current location" which will automatically show a users location on the map.

I'd like to move and zoom to this location when it's found (and if it changes).

The problem is, there doesn't appear to be any method called when the user location is updated on the map, so I have nowhere to put the code that will zoom/scroll.

Is there a way to be notified when an MKMapView has got (or updated) the user location so I can move/zoom to it? If I use my own CLLocationManager the updates I get do not correspond with the updates of the user marker on the map, so it looks silly when my map moves and zooms seconds before the blue pin appears.

This feels like basic functionality, but I've spent weeks looking for a solution and not turned up anything close.

like image 982
Danny Tuppeny Avatar asked Mar 18 '10 22:03

Danny Tuppeny


2 Answers

You have to register for KVO notifications of userLocation.location property of MKMapView.

To do this, put this code in viewDidLoad: of your ViewController or anywhere in the place where your map view is initialized.

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

Then implement this method to receive KVO notifications

- (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     } } 

This code works fine for me.
BTW, self is my ViewController in this context.

like image 90
ddnv Avatar answered Oct 07 '22 13:10

ddnv


This is a combination of ddnv and Dustin's answer which worked for me:

mapView is the name of the MKMapView *mapView;

In the viewDidLoad add this line, note there could be more lines in the load. This is just simplified.

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

Then create the actual listing method that moves the map to the current location:

// 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]; } 

Don't forget to dealloc properly and unregister the observer:

- (void)dealloc  {     [self.mapView.userLocation removeObserver:self forKeyPath:@"location"];     [self.mapView removeFromSuperview]; // release crashes app     self.mapView = nil;     [super dealloc]; } 
like image 45
MrHus Avatar answered Oct 07 '22 14:10

MrHus