Swift requestWhenInUseAuthorization not working

Andrea Giusti picture Andrea Giusti · May 1, 2016 · Viewed 9k times · Source

I'm writing an app for iOS 9.3 using swift and need a map to show user location. I initialize CLLocationManager and its delegate, I configure info.plist Privacy - Location Usage Description string and invoke requestWhenInUseAuthorization but it does not show any authorization request.

Here is my code:

import UIKit
import MapKit

class DetailController: UIViewController, CLLocationManagerDelegate {

    var locManager: CLLocationManager!

    @IBOutlet var myMap: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        mostraPosizione()
    }

    func mostraPosizione(){
        locManager = CLLocationManager()
        locManager.delegate = self
        locManager.desiredAccuracy = kCLLocationAccuracyBest

        let authorizationStatus = CLLocationManager.authorizationStatus()

        if (authorizationStatus == CLAuthorizationStatus.NotDetermined) {
            locManager.requestWhenInUseAuthorization()
        } else {
            locManager.startUpdatingLocation()
        }


        myMap.showsUserLocation = true
    }

    func locManager(manager: CLLocationManager, 
    didChangeAuthorizationStatus status: CLAuthorizationStatus) {

        if (status == CLAuthorizationStatus.NotDetermined) {
            locManager.requestWhenInUseAuthorization()

        } else {
            locManager.startUpdatingLocation()
        }
    }
}

and a screenshot from my info.plist info.plist

Xcode output:

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

I'm testing it on iPhone 5 s (iOS 9.3) simulator.

What's the problem with this stuff? Does anyone have any advice?

Answer

Chajmz picture Chajmz · May 2, 2016

I think it's because

let authorizationStatus = CLLocationManager.authorizationStatus()

is nil so your requestWhenInUseAuthorization() is never called.

  let authorizationStatus = CLLocationManager.authorizationStatus()

    if (authorizationStatus == CLAuthorizationStatus.NotDetermined) || (authorizationStatus == nil) {
        locManager.requestWhenInUseAuthorization()
    } else {
        locManager.startUpdatingLocation()
    }

should be working.

Edit:

You should also handle the case if the user decline the request

if (authorizationStatus == CLAuthorizationStatus.Denied ) {
  // Display a message, do what you want 
}

Indeed once the user has declined the authorization you can't make the popup appears again, users have to go in the app settings and set by themselves the authorization to use their location. However you can now have a link directly from your app to the settings, so it's easier for users.

// Open the settings of your app
if let url = NSURL(string:UIApplicationOpenSettingsURLString) {
    UIApplication.sharedApplication().openURL(url)
}