potato
potato

Reputation: 4589

requestWhenInUseAuthorization error only upon first launch

Error:

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

Code:

class ViewController: UIViewController {

    @IBOutlet weak var mapView: MKMapView!
    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()

        let currentLocationCoo = locationManager.location?.coordinate
        if let locationCoo = currentLocationCoo{
            mapView.region = MKCoordinateRegionMake(CLLocationCoordinate2D(latitude: locationCoo.latitude, longitude: locationCoo.longitude), MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
            print("location ni nil")
        }else{


        mapView.region = MKCoordinateRegionMake(CLLocationCoordinate2D(latitude: 52.05695, longitude: 14.50575), MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
        }

        let defaultAnnotation = MKPointAnnotation()
        defaultAnnotation.coordinate = mapView.region.center
        defaultAnnotation.title="Center"
        defaultAnnotation.subtitle="This is!"
        mapView.addAnnotation(defaultAnnotation)

        mapView.showsUserLocation=true
        mapView.showsBuildings=true
        mapView.userTrackingMode = .None

    }

I noticed that iOS throws the error only upon first launch. Before I even get to agree to location services prompt. On a subsequent launch it works fine. Is it because the first view controller the app launches already uses maps? Workaround is probably NOT to jump directly into maps, but first show some other VC. Any other workaround?

Upvotes: 0

Views: 120

Answers (1)

Vishnu gondlekar
Vishnu gondlekar

Reputation: 3956

Yes you are correct, mapView.showsUserLocation=true requires access to your current location and which is not possible without agreeing to alert shown by the OS. You can implement didChangeAuthorizationStatus method of CLLocationManagerDelegate and have your map related code inside it. Try out following code.

class ViewController: UIViewController,CLLocationManagerDelegate {

    @IBOutlet weak var mapView: MKMapView!
    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
    }

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case .AuthorizedWhenInUse:
            updateMap()
            break  
        case .AuthorizedAlways:
            updateMap()
            // write your map related code here
            break
        default:
            break
        }
    }

    func updateMap() {
        let currentLocationCoo = locationManager.location?.coordinate
        if let locationCoo = currentLocationCoo{
            mapView.region = MKCoordinateRegionMake(CLLocationCoordinate2D(latitude: locationCoo.latitude, longitude: locationCoo.longitude), MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
            print("location ni nil")
        }else{
            mapView.region = MKCoordinateRegionMake(CLLocationCoordinate2D(latitude: 52.05695, longitude: 14.50575), MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002))
        }

        let defaultAnnotation = MKPointAnnotation()
        defaultAnnotation.coordinate = mapView.region.center
        defaultAnnotation.title="Center"
        defaultAnnotation.subtitle="This is!"
        mapView.addAnnotation(defaultAnnotation)

        mapView.showsUserLocation=true
        mapView.showsBuildings=true
        mapView.userTrackingMode = .None
    }
}

Upvotes: 1

Related Questions