MKMapView setRegion: crashes at edge of world
Asked Answered
O

4

7

I am using this code to set the region of an MKMapView such that it is centred around pin and zoomed to show an approximate 10km area.

CLLocationAccuracy accuracy = kCLLocationAccuracyKilometer;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(pin.coordinate, accuracy * 10.0f, accuracy * 10.0f);
[self.mapSubView setRegion:region animated:NO];

When running the code with a pin coordinate of latitude -90, longitude -58.359001159667969 the region is generated as shown:

A crash occurs when the mapSubView is drawn:-

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid Region <center:-90.00000000, -58.35900116 span:+0.08953039, +1462142065660629.00000000>'

My first attempt at fixing this was to check for "edge" lat/long (-90, +90, -180, +180), which solved the issue. However if the latitude changes to -89.99999 the problem returns.

I'm guessing this is due to a combination of the latitude being -90 and/or the region span's longitude delta being so large resulting in a region that is effectively "out of this world" :p

Any advice as to how to centre the map around a pin at any coordinate, showing a ~10km area, without this crash would be greatly appreciated.

Otoplasty answered 16/4, 2014 at 14:3 Comment(0)
B
7

@supp-f answer is right

Swift 3 solution:

func safeSetRegion(_ region: MKCoordinateRegion) {
    let myRegion = self.mapView.regionThatFits(region)
    if !(myRegion.span.latitudeDelta.isNaN || myRegion.span.longitudeDelta.isNaN) {
        self.mapView.setRegion(myRegion, animated: true)
    }
}
Burnejones answered 22/2, 2017 at 16:35 Comment(1)
There should at least be a "this function can occasionally return NaN for the span for no apparent reason" in the documentationOulman
S
4

First, adjust map region with regionThatFits: method. Then, compare result span deltas with nan value. You should have something like this:

region = [self.mapView regionThatFits:region];
if (!isnan(region.span.latitudeDelta) && !isnan(region.span.longitudeDelta)) {
  [self.mapView setRegion:region animated:YES];
}
Softa answered 20/12, 2015 at 21:26 Comment(0)
J
3

Based on the answers of Sergey and supp-f, you also have to check for maximum span values.

Maximum for latitude span is 180.0, maximum for longitude span is 360.0

func safeSetRegion(_ region: MKCoordinateRegion) {
    let myRegion = self.mapView.regionThatFits(region)
    if !(myRegion.span.latitudeDelta.isNaN || myRegion.span.longitudeDelta.isNaN) {

        // check for maximum span values (otherwise the setRegion(myRegion) call will crash)
        let deltaLat = min(180.0, myRegion.span.latitudeDelta)
        let deltaLong = min(360.0, myRegion.span.longitudeDelta)

        // now build a nice and easy span ...
        let coordinatesRegionWithSpan =  MKCoordinateSpan(
                     latitudeDelta: deltaLat,
                     longitudeDelta: deltaLong)

        // ... to use for an adjusted region
        let adjustedCoordinateRegion = MKCoordinateRegion(
            center: region.center,
            span: coordinatesRegionWithSpan)

        // and now it's safe to call
        self.mapView.setRegion(adjustedCoordinateRegion, animated: true)
    }
}
Jessen answered 15/8, 2018 at 19:15 Comment(0)
P
0

I was able to reproduce the crash. I think it's a bug in the SDK.

And this test will also fail, but with not crash:

MKCoordinateRegion region;
region.center.longitude = coord.longitude;
region.center.latitude = 90.f;//coord.latitude;
region.span.longitudeDelta = 0.02f;
region.span.latitudeDelta = 0.02f;

[self.mapView setRegion:region animated:NO];

That would be a stable version. Only here, the region is then very large. You can test the delta values if there a NSNotFound

Puffin answered 16/4, 2014 at 15:1 Comment(2)
Checking the delta values against NSNotFound doesn't work, see this console output:- Longitude span: 1462142065660629.000000 vs NSNotFound: 2147483647Otoplasty
Yes you are right. My mistake but i think this is also a MAX value defined somewhere. A very bad work a round is to test if the span is an absurd value. I´ve search in the Apple developer forums for this issue but i found nothing. Sorry but not now I know more.Puffin

© 2022 - 2024 — McMap. All rights reserved.