How can I prompt the user to turn on location serv

2019-01-07 05:48发布

I have an application with an explicit user interaction that makes use of the user's current location. If the user denies access to location services, I would still like subsequent uses to prompt the user to go to settings and re-enable location services for my app.

The behavior I want is that of the built-in Maps app:

  1. Reset location warnings in Settings > General > Reset > Reset Location Warnings.
  2. Start Maps app.
  3. Tap Current Location button in lower left corner.
  4. Maps prompts with ""Maps" Would Like to Use Your Current Location" | "Don't Allow" | "Allow".
  5. Choose "Don't Allow" option.
  6. Tap Current Location button in lower left corner again.
  7. Maps prompts with "Turn On Location Services to Allow "Maps" to Determine Your Location" | "Settings" | "Cancel".

In my own app, the same basic flow results in my CLLocationManagerDelegate -locationManager:didFailWithError: method being called with a kCLErrorDenied error at the final step and the user is not given the option to open the Settings app to correct it.

I could display my own alert in response to the error, but it would not have the ability to launch the Settings app like the alert that the OS can provide as used by the built-in Maps app.

Is there something in the CLLocationManager class I am missing that would be able to give me this behavior?

11条回答
Rolldiameter
2楼-- · 2019-01-07 06:09

I guess you will have an answer to your question when Apple will think about a new SDK. At current time and as far as I know, it's not possible :

No URL-Handler available
No usable method to call

But... As Maps does it, this CAN be done, but probably using a private API. If you're not afraid with this kind of coding, you should search there in my opinion.

查看更多
Juvenile、少年°
3楼-- · 2019-01-07 06:09

Swift,

Once you disable location services for an app, location manager delegate methods will start showing error. So, on receiving error we can check if location services are enabled/disabled. And according to the result, we can ask the user to go to settings and turn on location services.

In your location manager delegate method for error, add location permission check

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
            //check  location permissions
            self.checkLocationPermission()
        }
}

Code for location permission checking

//check location services enabled or not

    func checkLocationPermission() {
        if CLLocationManager.locationServicesEnabled() {
            switch(CLLocationManager.authorizationStatus()) {
            case .notDetermined, .restricted, .denied:
                //open setting app when location services are disabled
            openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
            case .authorizedAlways, .authorizedWhenInUse:
                print("Access")
            }
        } else {
            print("Location services are not enabled")
            openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
        }
    }

Code to open settings app,

//open location settings for app
func openSettingApp(message: String) {
    let alertController = UIAlertController (title: APP_NAME_TITLE, message:message , preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: NSLocalizedString("settings", comment: ""), style: .default) { (_) -> Void in
        guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
        }
    }
    alertController.addAction(settingsAction)
    let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .default, handler: nil)
    alertController.addAction(cancelAction)

    present(alertController, animated: true, completion: nil)
}
查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-01-07 06:14

AlertViews are deprecated in iOS 8. There is now a better way to handle alerts using the new AlertController:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString( @"Enter your title here", @"" ) message:NSLocalizedString( @"Enter your message here.", @"" ) preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Cancel", @"" ) style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Settings", @"" ) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
   [[UIApplication sharedApplication] openURL:[NSURL URLWithString:
                                                    UIApplicationOpenSettingsURLString]];
}];

[alertController addAction:cancelAction];
[alertController addAction:settingsAction];

[self presentViewController:alertController animated:YES completion:nil];
查看更多
乱世女痞
5楼-- · 2019-01-07 06:17

Here's a Swift version of the code in the answer by Markus. This code creates an alert that gives the user the option to open Settings.

let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .Alert)

let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (UIAlertAction) in
    UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}

alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.presentViewController(alertController, animated: true, completion: nil)
查看更多
老娘就宠你
6楼-- · 2019-01-07 06:18

In Swift 4, there is an update in its syntax.

Swift 4

extension UIAlertController {

    func createSettingsAlertController(title: String, message: String) {

      let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)

      let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
      let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
        UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)! as URL, options: [:], completionHandler: nil)
      }

      alertController.addAction(cancelAction)
      alertController.addAction(settingsAction)
      self.present(alertController, animated: true, completion: nil)

   }
}
查看更多
登录 后发表回答