¿Cómo acerco un MKMapView a la ubicación actual de los usuarios sin CLLocationManager?

Con MKMapView hay una opción llamada “Mostrar la ubicación actual de los usuarios” que mostrará automáticamente la ubicación de los usuarios en el map .

Me gustaría moverme y acercarme a esta ubicación cuando se encuentre (y si cambia).

El problema es que no parece haber ningún método llamado cuando la ubicación del usuario se actualiza en el map , por lo que no tengo dónde colocar el código que se zoom/scroll .

¿Hay alguna manera de recibir notificaciones cuando MKMapView tiene (o actualiza) la ubicación del usuario para poder moverlo / acercarme a él? Si utilizo mi propio CLLocationManager las actualizaciones que recibo no se corresponden con las actualizaciones del marcador de usuario en el mapa, por lo que parece tonto cuando mi mapa se mueve y hace zoom unos segundos antes de que aparezca el pin azul.

Esto parece una funcionalidad básica, pero he pasado semanas buscando una solución y no encontré nada cerca.

Debe registrarse para las notificaciones de userLocation.location propiedad MKMapView de MKMapView .

Para hacer esto, coloque este código en viewDidLoad: de su ViewController o en cualquier lugar del lugar donde se inicializa su vista de mapa.

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

A continuación, implemente este método para recibir notificaciones de 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 } } 

Este código funciona bien para mí.
Por cierto, self soy mi ViewController en este contexto.

Esta es una combinación de ddnv y la respuesta de Dustin que funcionó para mí:

mapView es el nombre de MKMapView * mapView;

En viewDidLoad agregue esta línea, tenga en cuenta que podría haber más líneas en la carga. Esto simplemente se simplifica.

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

Luego, crea el método de listado real que mueve el mapa a la ubicación actual:

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

No olvide desasignar correctamente y anular el registro del observador:

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

Desde iOS 5.0, Apple ha agregado un nuevo método a MKMapView. Este método hace exactamente lo que quiere y más.

Eche un vistazo a: https://developer.apple.com/documentation/mapkit/mkmapview

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

Puede supervisar cuándo MKMapView actualiza la ubicación del usuario en el mapa mediante la implementación del protocolo MKMapViewDelegate . Solo implemente:

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

Esta callback debe estar perfectamente sincronizada con lo que se muestra en el mapa.

Prueba esto:

 [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES]; 

No hay problema … Dentro del método viewDidLoad de su subclase UIViewController que tiene MKMapView agregue esto (suponiendo que su MKMapView se llame 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