MKMapView's user location is wrong on startup or resume

DeShawn Terrell picture DeShawn Terrell · Feb 9, 2011 · Viewed 7.1k times · Source

When I start my application fresh, or resume after a long time, MKMapView's notion of the userLocation is wrong and shows me in the middle of the sea.

I am using the following code:

self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;
[mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate zoomLevel:ZOOM_LEVEL animated:YES];

Happens after a lengthy resume of the app or brand new start....

Answer

yonel picture yonel · Nov 3, 2011

That's the expected behavior : the user location isn't always tracked by the iPhone using GPS (it would consume to much battery). So as soon as the map is displayed, the MKMapView instance shows the last 'best' user position it knows and then, improves the accuracy by activating the tracking (this is a seamless process, you don't have to care about it) .

You can monitor when the MKMapView updates the user location on the map by implementing the MKMapViewDelegate protocol. Just implement :

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

(More info from the apple documentation here )

The code above in my example checks the accuracy of the position currently being displayed by the mapView and reacts accordingly.

[EDIT]
If showing the user location in the middle of the sea at first really bother you, you can you hide the user location until you get a location that is accurate/fresh enough.
To do so, set the showsUserLocation property of the MKMapView to NO at first until you get an accurate enough location (thanks to the previous delegate callback) and then set it to YES.
By doing you, you will avoid displaying a location that is not accurate or too old to be diplayed (there is a timestamp property in the CLLocation to check wether it's an old location or not)

N.B:You don't have to create a CLLocationManager instance on your side, the MKMapView creates one internally and publish locations it receives via this delegate selector.