Как я могу предложить пользователю включить службы определения местоположения после того, как пользователь отказался от их использования - PullRequest
69 голосов
/ 04 февраля 2011

У меня есть приложение с явным взаимодействием с пользователем, которое использует текущее местоположение пользователя. Если пользователь отказывает в доступе к службам определения местоположения, я по-прежнему хотел бы, чтобы последующее использование предлагало пользователю перейти к настройкам и повторно включить службы определения местоположения для моего приложения.

Мне нужно поведение встроенного приложения Карт:

  1. Сброс предупреждений о местоположении в меню «Настройки»> «Основные»> «Сброс»> «Сброс предупреждений о местоположении».
  2. Запустите приложение Карт.
  3. Нажмите кнопку «Текущее местоположение» в левом нижнем углу.
  4. Запросы карт с «« Карты »хотели бы использовать ваше текущее местоположение» | "Не разрешать" | "Разрешить".
  5. Выберите опцию «Не разрешать».
  6. Снова нажмите кнопку «Текущее местоположение» в левом нижнем углу.
  7. Карты запрашивают «Включить службы определения местоположения, чтобы разрешить« Карточкам »определять ваше местоположение» | «Настройки» | "Отменить".

В моем собственном приложении тот же основной поток приводит к тому, что мой CLLocationManagerDelegate -locationManager: didFailWithError: метод, вызываемый с ошибкой kCLErrorDenied на последнем этапе, и пользователю не предоставляется возможность открыть приложение «Настройки» для его исправления.

Я мог бы отобразить свое собственное предупреждение в ответ на ошибку, но у него не было бы возможности запустить приложение «Настройки», как предупреждение, которое ОС может выдавать при использовании встроенного приложения «Карты».

Есть ли в классе CLLocationManager что-то, чего мне не хватает, что могло бы дать мне такое поведение?

Ответы [ 11 ]

42 голосов
/ 14 августа 2014

С iOS8 вы можете, наконец, связать пользователя с приложением Настройки через openURL. Например, вы можете создать UIAlertView с помощью одной кнопки, которая переводит пользователя в приложение «Настройки»:

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ICLocalizedString(@"LocationServicesPermissionTitle")
                                                    message:ICLocalizedString(@"LocationPermissionGeoFenceMessage")
                                                   delegate:self
                                          cancelButtonTitle:@"Settings"
                                          otherButtonTitles:nil];
    [alert show];

В вашем делегате UIAlertView:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
    [[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
32 голосов
/ 10 сентября 2011

Обновление:

Начиная с iOS 8, теперь есть константа UIApplicationOpenSettingsURLString, представляющая URL-адрес, который при открытии открывает приложение «Настройки» для настроек вашего приложения (гдепользователь может затем повторно включить службы определения местоположения).


Оригинал:

Невозможно сделать это.Единственный реальный вариант - отобразить предупреждение, информирующее пользователя о том, что вашему приложению требуются службы определения местоположения, и дать им указание вручную перейти в приложение «Настройки» и включить его.

16 голосов
/ 12 марта 2015

AlertViews устарело в iOS 8. Теперь есть лучший способ обработки оповещений с помощью нового 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];
6 голосов
/ 29 января 2017

Вот быстрая 3 реализация кода, предоставленного Маркусом и bjc.

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.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
            }

alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
            self.present(alertController, animated: true, completion: nil)
6 голосов
/ 01 июля 2012

Согласно Документам Apple по методу locationServicesEnabled .

Пользователь может включать или отключать службы определения местоположения из приложения "Настройки", переключая службы определения местоположения.Переключиться в общем.

Необходимо проверить возвращаемое значение этого метода перед началом обновления местоположения, чтобы определить, есть ли у пользователя службы определения местоположения, включенные для текущего устройства. Если этот метод возвращает NO и вы все равно запускаете обновления местоположения, базовая структура местоположения предлагает пользователю подтвердить, следует ли включить службы определения местоположения.

Так что вы не можете просто запустить службы определения местоположенияобновляет ли какой-либо способ вызвать предупреждение?

3 голосов
/ 18 января 2018

В Swift 4 есть обновление в его синтаксисе.

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)

   }
}
2 голосов
/ 10 сентября 2011

Полагаю, у вас будет ответ на ваш вопрос, когда Apple подумает о новом SDK. В настоящее время и, насколько я знаю, это невозможно:

URL-обработчик недоступен
Нет используемого метода для вызова

Но ... Как это делает Maps, это МОЖЕТ быть сделано, но, вероятно, с использованием частного API. Если вы не боитесь такого рода кодирования, вы должны искать там, по моему мнению.

1 голос
/ 12 июня 2018

Swift

Как только вы отключите службы определения местоположения для приложения, методы делегата менеджера местоположения начнут показывать ошибку. Таким образом, при получении ошибки мы можем проверить, включены ли службы определения местоположения. И в зависимости от результата мы можем попросить пользователя перейти в настройки и включить службы определения местоположения.

В методе делегата менеджера местоположений для ошибки добавьте проверку разрешения местоположения

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

Код для проверки разрешения местоположения

//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: ""))
        }
    }

Код для открытия настроек приложения,

//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)
}
1 голос
/ 18 января 2017

Вот Swift-версия кода в ответе Маркуса. Этот код создает предупреждение, которое дает пользователю возможность открыть Настройки.

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)
0 голосов
/ 28 августа 2018

последняя версия swift, основанная на ответах выше.

func showSettingsAlert(_ from:UIViewController, 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

            guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                return
            }

            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
            }
        }

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