Alan
Alan

Reputation: 305

My app crashes when attempting to setup my map view

I'm trying to integrate a styled Google Map into my iOS app that I'm programming in Swift. I have a view in my storyboard that is a GMSMapView, and I'm trying to color it with custom JSON. Here is the code for making the mapView:

@IBOutlet weak var mapView: GMSMapView!

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let userLocation = locations.last
    //let center = CLLocationCoordinate2D(latitude: userLocation!.coordinate.latitude, longitude: userLocation!.coordinate.longitude)

    let camera = GMSCameraPosition.camera(withLatitude: userLocation!.coordinate.latitude,
                                          longitude: userLocation!.coordinate.longitude, zoom: 13.0)

    mapView.isMyLocationEnabled = true
    mapView.camera = camera
    self.view = mapView

    locationManager.stopUpdatingLocation()
}

override func loadView() {
    do {
        // Set the map style by passing the URL of the local file.
        if let styleURL = Bundle.main.url(forResource: "style", withExtension: "json") {
***error->            self.mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
        } else {
            NSLog("Unable to find style.json")
        }
    } catch {
        NSLog("One or more of the map styles failed to load. \(error)")
    }
}

but when I try to run it, I get a fatal error:

unexpectedly found nil while unwrapping an Optional value

The line that throws the error is the one with the *** on it. I've linked the GMSMapView with the View on the storyboard, and the app compiles correctly without trying to style it. Does anyone know why this error is occurring? I've Googled the error but couldnt find anything that relates to my code, and I couldn't understand what some of the links wanted me to do.

Upvotes: 0

Views: 1457

Answers (1)

rmaddy
rmaddy

Reputation: 318774

The error is because self.mapView is nil. Here's why:

Your map view is setup as an outlet to your storyboard. In this case, your map view will be created for you. Just make sure the map view is actually connected to the outlet.

The real issue is that you have overloaded the loadView method. Don't do that. From the docs for UIViewController loadView:

If you use Interface Builder to create your views and initialize the view controller, you must not override this method.

The code you currently have in loadView should be moved to the viewDidLoad method.

override func viewDidLoad() {
    super.viewDidLoad()

    do {
        // Set the map style by passing the URL of the local file.
        if let styleURL = Bundle.main.url(forResource: "style", withExtension: "json") {
            self.mapView.mapStyle = try GMSMapStyle(contentsOfFileURL: styleURL)
        } else {
            NSLog("Unable to find style.json")
        }
    } catch {
        NSLog("One or more of the map styles failed to load. \(error)")
    }

    // and any other code you might need in viewDidLoad
}

The next big issue is that you assign a value to self.view inside the location manager delegate. That's bad too. The only place you should ever assign something to self.view in a view controller is in loadView and only if you are creating the whole view controller and its view programmatically.

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let userLocation = locations.last
    //let center = CLLocationCoordinate2D(latitude: userLocation!.coordinate.latitude, longitude: userLocation!.coordinate.longitude)

    let camera = GMSCameraPosition.camera(withLatitude: userLocation!.coordinate.latitude,
                                          longitude: userLocation!.coordinate.longitude, zoom: 13.0)

    mapView.isMyLocationEnabled = true
    mapView.camera = camera

    locationManager.stopUpdatingLocation()
}

Summary:

  1. Remove the loadView method. Move its contents to viewDidLoad
  2. Don't assign to self.view any where in your code.
  3. Make sure the map view in your storyboard is really connected to your outlet.

Upvotes: 2

Related Questions