Why will MKCoordinateRegion not show a small region?

79 Views Asked by At

I have the following code to set an MKCoordinateRegion to an MKMapView:

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.showsUserLocation = true
    mapView.setUserTrackingMode(.followWithHeading, animated: true)

    currentLocationCoordinateRegion = MKCoordinateRegion(center: mapView.userLocation.coordinate, latitudinalMeters: 25, longitudinalMeters: 25)
    mapView.setRegion(currentLocationCoordinateRegion, animated: true)

    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    locationManager.distanceFilter = kCLDistanceFilterNone

    let status = CLLocationManager.authorizationStatus()

    if status == .authorizedAlways || status == .authorizedWhenInUse, status == .restricted {

    } else {

        locationManager.requestAlwaysAuthorization()

    }

}

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {

    if currentLocationCoordinateRegion == nil {

        currentLocationCoordinateRegion = MKCoordinateRegion(center: mapView.userLocation.coordinate, latitudinalMeters: 25, longitudinalMeters: 25)

        mapView.setRegion(currentLocationCoordinateRegion, animated: true)

    }

}

However, the map view shows a region that is much larger than 20 meters by 20 meters.

What is the problem and how do I fix it?

2

There are 2 best solutions below

6
daniel On

I tried running that code after the first time it is run, and the second time it works. It just doesn't zoom completely the first time.

0
matt On

The problem is probably here:

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
    if currentLocationCoordinateRegion == nil { // <--
        currentLocationCoordinateRegion = MKCoordinateRegion(center: mapView.userLocation.coordinate, latitudinalMeters: 25, longitudinalMeters: 25)
        mapView.setRegion(currentLocationCoordinateRegion, animated: true)
    }
}

Here's my theory. As we get started, Core Location tries to get a fix on the user's location. At first it has only a vague idea where the user is, and you get didUpdate. But then (with luck) it gets better and better ideas where the user, and you get didUpdate again. And again. And again, until we have a good fix. But you are throwing away the second, third, fourth updates — you stop as soon as you get the first update. That, I'm suggesting, would be why it works better the second time; Core Location has had time to get a better fix.