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....
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.