1

I have an app that finds places near the user’s location, however, the app crashes the second time it runs with the exception: fatal error: unexpectedly found nil while unwrapping an Optional value. On line: self.googleMapView.animate(toLocation: coordinates)

I checked and the googleMapView is nil but I don’t understand how it is nil or how it ran the first time. It only starts crashing on subsequent tries if I delete and reinstall the app it works fine on the first try but after that it keeps crashing even if I restart the app. Full code below

import UIKit
import GoogleMaps
import GooglePlacePicker
import MapKit

 class MapViewController: UIViewController, CLLocationManagerDelegate {
var currentLongitude: CLLocationDegrees = 0
var currentLatitude: CLLocationDegrees = 0
var locationManager: CLLocationManager!
var placePicker: GMSPlacePickerViewController!
var googleMapView: GMSMapView!

@IBOutlet weak var mapViewContainer: MKMapView!

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.googleMapView = GMSMapView(frame: self.mapViewContainer.frame)
    self.googleMapView.animate(toZoom: 18.0)
    self.view.addSubview(googleMapView)
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.locationManager = CLLocationManager()
    self.locationManager.delegate = self
    self.locationManager.requestAlwaysAuthorization()
    self.locationManager.requestWhenInUseAuthorization()
    self.locationManager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location:CLLocation = locations.last {
        self.currentLatitude = location.coordinate.latitude
        self.currentLongitude = location.coordinate.longitude
    }
    else {
        print("Location Error")
    }

    let coordinates = CLLocationCoordinate2DMake(self.currentLatitude, self.currentLongitude)
    let marker = GMSMarker(position: coordinates)
    marker.title = "I am here"
    marker.map = self.googleMapView
    self.googleMapView.animate(toLocation: coordinates)
}



private func locationManager(manager: CLLocationManager,
                     didFailWithError error: Error){
    print("An error occurred while tracking location changes : \(error.localizedDescription)")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Marij Khan
  • 151
  • 1
  • 12
  • after it works first time, you killed and then restarted it and still it crashes??? – Karthick Ramesh Nov 02 '18 at 01:25
  • Yes. It is only after I reinstall it that it starts working – Marij Khan Nov 02 '18 at 04:59
  • @KarthickRamesh I fixed the crash by moving the viewDidAppear code to viewDidLoad and everything seems to work fine but I don't understand what the problem was. The tutorial I am following used the viewDidAppear instead of viewDidLoad explaining that viewDidLoad is called too soon. This [link](http://sweettutos.com/2015/10/26/how-to-get-nearby-places-by-implementing-the-google-place-picker-in-ios/) is the tutorial – Marij Khan Nov 02 '18 at 07:50
  • You have to add the logic to animate in main thread i think. It will work even in viewWillAppear in that case. – Karthick Ramesh Nov 02 '18 at 07:53
  • Did the previous point that i mentioned worked? The second point, can you modify the question? The solution is simple. You need to remove the old markers and add a new marker. – Karthick Ramesh Nov 02 '18 at 08:00
  • @KarthickRamesh, Yes it worked like a charm, although I did it in viewDidAppear instead of viewWillAppear. Also, fixed the mark thing by moving it to viewDidAppear as I don't need to keep updating the marker. Just loading it once is fine. Thanks for all the help – Marij Khan Nov 02 '18 at 08:57

1 Answers1

0

Crash is pretty self-explanatory:

You are setting your location's delegate in the viewDidLoad but creating the map in the viewDidAppear.

If the location was known by iOS, you will receive the message before viewDidAppear call so in the line : self.googleMapView.animate(toLocation: coordinates), your map is still nil

You can either define your map as optional : var googleMapView: GMSMapView?, or you can wait for your map to be defined to create your location Manager.

CZ54
  • 5,488
  • 1
  • 24
  • 39
  • " If the location was known by iOS, you will receive the message before viewDidAppear " Is that why it runs fine the first time? In subsequent tries locations.last contains something so the message gets sent before viewDidAppear but not in the case of the first try. – Marij Khan Nov 02 '18 at 08:31
  • Yes, that's why – CZ54 Nov 02 '18 at 08:44