0

Fist time when I install my iOS app on a device via xcode and location service is off, requestAlwaysAuthorization() shows "Turn on location services" that push user to device Settings to turn on location service, then user comes back to the app and would see "permission" alert(with three options always, while using and never). If user taps on always option then closes the app completely and turns location service off then opens app again, "Turn on location services" alert is not displayed. This is my code:

override func viewDidLoad() {
    super.viewDidLoad()

    locationManager = CLLocationManager()
    NotificationCenter.default.addObserver(self, selector: #selector(checkLocationService), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)    
}

 @objc func checkLocationService() {
    if CLLocationManager.locationServicesEnabled() {
        switch CLLocationManager.authorizationStatus() {
        case .denied, .notDetermined, .restricted:
            locationManager = CLLocationManager()
            locationManager.delegate = self
            locationManager.requestAlwaysAuthorization()
        case .authorizedWhenInUse, .authorizedAlways:
            ...
        }
    } else {
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
    }
}

I've added all three location keys in the Info.plist:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>My app need your location to work</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>My app need your location to work</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>My app need your location to work</string>

I am testing on iOS 11 and 12 and I have no idea what is wrong.

Hasti Ranjkesh
  • 643
  • 10
  • 26
  • 2
    You only request auth once... if the user grants permission then you dont need to ask again and if they refuse you can't prompt again. you need to handle it differently if denied. you push the user to the app settings in the settings menu and the user has to enable from there – Scriptable Nov 14 '18 at 11:37
  • @Scriptable Thanks for your reply, I tried to show an alert to push the user to settings/privacy/location service via "Prefs:root=Privacy&path=LOCATION", but it just shows setting page. Do you know how can I push the user to privacy -> location service? – Hasti Ranjkesh Nov 14 '18 at 12:14
  • `if let url = URL(string: UIApplicationOpenSettingsURLString) { UIApplication.shared.open(url: url) }` – Scriptable Nov 14 '18 at 12:46
  • UIApplicationOpenSettingsURLString opens my app setting, If location service is off I can not change permission in thre app setting, I need to turn location service on. – Hasti Ranjkesh Nov 14 '18 at 13:57
  • You have missed the point of my first comment. if the user denies the location permission for YOUR app, then you need to change it in YOUR app settings. the problem is not the global location services permission, its the permissions for your app specifically. See the **denied** case in the code below – Scriptable Nov 14 '18 at 14:09
  • The senario is this: user does not deny the location permission, at first run user turns locatuon service on and allows the app to use location service. After that when user closes the app and turns location service off then opens the app, I think this line of code (locationManager.requestAlwaysAuthorization()) would show the alert with this message "Turn on Location Services to Allow ... to Determine Your Location", like waze, with two action: 1-Settings 2-Cancel. When user tap settings action, user goes to settings->privacy->location service. – Hasti Ranjkesh Nov 14 '18 at 16:45

1 Answers1

2

You only request auth once... if the user grants permission then you dont need to ask again and if they refuse you can't prompt again. you need to handle it differently if denied. you push the user to the app settings in the settings menu and the user has to enable from there

switch CLLocationManager.authorizationStatus() {
    case .notDetermined, .restricted:
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
    case .authorizedWhenInUse, .authorizedAlways:
        ...
    case .denied:
        // present an alert advising the user that they need to go to the settings menu to enable the permissions as they have previously denied it. 
        // if the user presses Open Settings on the alert....
        if let url = URL(string: UIApplicationOpenSettingsURLString) { 
            UIApplication.shared.open(url: url) 
        }
    }
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • My problem is how can I show "Turn on Location Services to Allow ... to Determine Your Location" alert when location service if off? If I should implement my custom alert, how can I route user to Settings -> privacy -> location service? – Hasti Ranjkesh Nov 14 '18 at 17:03
  • 1
    I dont know how you goto the global location services screen directly. see: https://stackoverflow.com/questions/37654132/how-to-open-location-services-screen-from-setting-screen – Scriptable Nov 14 '18 at 18:03
  • I think it's impossible. Avoid use of "prefs:root" or "App-Prefs:root" in your app, otherwise App will be rejected from App Store. Just open Setting page. – Hasti Ranjkesh Nov 15 '18 at 12:56