user2722667 user2722667 - 1 month ago 18
iOS Question

Swift MKMapView sometimes becomes nil and app crashes

I am displaying a map like this:

//Map
@IBOutlet var mapView: MKMapView!

var location: String?

override func viewDidLoad() {
super.viewDidLoad()

self.mapView.delegate = self

if let location = location {
let address = location
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let placemarks = placemarks {
if placemarks.count != 0 {
let annotation = MKPlacemark(placemark: placemarks.first!)
self.mapView.addAnnotation(annotation)
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegionMake(annotation.coordinate, span)
self.mapView.setRegion(region, animated: false)
}
}
}
}
}

//Fixing map memory issue
override func viewWillDisappear(_ animated:Bool){
super.viewWillDisappear(animated)
self.applyMapViewMemoryFix()
}

//Fixing map memory issue
func applyMapViewMemoryFix(){
switch (self.mapView.mapType) {
case MKMapType.hybrid:
self.mapView.mapType = MKMapType.standard
break;
case MKMapType.standard:
self.mapView.mapType = MKMapType.hybrid
break;
default:
break;
}
self.mapView.showsUserLocation = false
self.mapView.delegate = nil
self.mapView.removeFromSuperview()
self.mapView = nil
}


If I exit out from the VC and go back again a few times fast the app will eventually crash because MKMapView becomes nil.

The crash happens here self.mapView.addAnnotation(annotation)

I am not sure why but my guess is that
geocoder.geocodeAddressString
has not finished loading/searching and if I exit out from the VC fast enough
mapView
becomes nil

Answer

You set self.mapView to nil in your viewWillDisappear method. So your app will crash anytime you leave the view controller before the geocoder is done.

Simply add a proper check for nil in the geocoder block.

override func viewDidLoad() {
    super.viewDidLoad()

    self.mapView.delegate = self

    if let location = location {
        let address = location
        let geocoder = CLGeocoder()
        geocoder.geocodeAddressString(address) { (placemarks, error) in
            if let placemarks = placemarks {
                if placemarks.count != 0 {
                    if let mapView = self.mapView {
                        let annotation = MKPlacemark(placemark: placemarks.first!)
                        mapView.addAnnotation(annotation)
                        let span = MKCoordinateSpanMake(0.1, 0.1)
                        let region = MKCoordinateRegionMake(annotation.coordinate, span)
                        mapView.setRegion(region, animated: false)
                    }
                }
            }
        }
    }
}