Як я можу запропонувати користувачеві ввімкнути служби локації після того, як користувач відмовив у їх використанні


75

У мене є програма з явною взаємодією користувача, яка використовує поточне місцезнаходження користувача. Якщо користувач відмовляє у доступі до служб визначення місцезнаходження, я все одно хотів би, щоб подальше використання спонукало користувача перейти до налаштувань і повторно ввімкнути служби визначення місцезнаходження для мого додатка.

Мені потрібна поведінка вбудованої програми Карти:

  1. Скиньте попередження про місцезнаходження в Налаштування> Загальне> Скинути> Скинути попередження про місцезнаходження.
  2. Запустіть додаток Карти.
  3. Торкніться кнопки Поточне місце розташування в нижньому лівому куті.
  4. Підказки Карт із "" Картами "Я хочу використати ваше поточне місцезнаходження" | "Не дозволяти" | "Дозволити".
  5. Виберіть опцію "Не дозволяти".
  6. Знову торкніться кнопки Поточне місце розташування в нижньому лівому куті.
  7. Карти підказують "Увімкнути служби локації, щоб дозволити" Картам "визначати ваше місцезнаходження" | "Налаштування" | "Скасувати".

У моєму власному додатку той самий основний потік призводить до мого CLLocationManagerDelegate -locationManager: didFailWithError: метод, що викликається з помилкою kCLErrorDenied на завершальному кроці, і користувач не має можливості відкрити програму Налаштування для її виправлення.

Я міг відобразити своє власне сповіщення у відповідь на помилку, але воно не могло б запускати програму Налаштування, як попередження, яке може надати ОС за допомогою вбудованої програми Карти.

Чи є щось у класі CLLocationManager, якого мені не вистачає, і що могло б дати мені таку поведінку?


Зараз я просто вивожу сповіщення користувачеві з проханням перейти в Налаштування, щоб його знову ввімкнути. Я б також хотів почути краще рішення.
донкім

Я хотів би отримати відповідь і на це, безумовно, є кращий спосіб
conorgriffin

Я виявив, що CoreLocation не задовольняє з цієї причини. У підсумку я використав бібліотеку skyhook, яку легко інтегрувати та добре документувати. Здається, координати також є більш точними. Єдиним недоліком є ​​необхідність поєднувати 1,5 МБ дилібу з додатком.
Кріс Моуфорт,

Я думаю, що багато відповідей показують відповіді на stackoverflow.com/questions/5655674/…
Прамод Детальніше

Відповіді:


42

З 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]];
}

4
Це набагато краще, ніж це можна було зробити в iOS 7 і раніше, але все ще не є ідеальним, оскільки URL-адреса переходить на екран вище рівня, де користувач може насправді змінити налаштування.
GBegen

Принаймні станом на iOS 10, ви перейдете прямо до налаштувань програми, де також вказано місцезнаходження.
Морське узбережжя Тибету

32

Оновлення:

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


Оригінал:

Ви не можете цього зробити. Ваш єдиний реальний варіант - відобразити сповіщення, в якому повідомляється користувачеві про те, що вашій програмі потрібні послуги визначення місцезнаходження, та вказується вручну перейти до програми Налаштування та ввімкнути її.


Я читав у Apple Docs і опублікував відповідь нижче, виходячи з документів, але я ще не перевіряв це сам. Це зміна SDK чи вони однакові.
Просто кодер

Боюся, що ця відповідь більше не правильна. Можливо, ви захочете оновити або видалити свою відповідь.
Джеймс Вебстер,

Ось чудовий приклад у Swift nshipster.com/core-location-in-ios-8, який я знайшов справді корисним. Він показує, як зробити попередження, яке переспрямовує на Settingsвикористання UIApplicationOpenSettingsURLString.
dmk12

17

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];

7

Згідно з документами Apple щодо методу locationServicesEnabled .

Користувач може ввімкнути або вимкнути служби визначення місцезнаходження з програми Налаштування, перемикаючи перемикач Служб локації в загальному.

Вам слід перевірити повернене значення цього методу перед початком оновлення місцезнаходження, щоб визначити, чи ввімкнено користувачем служби локації для поточного пристрою. Якщо цей метод повертає НІ, і ви в будь-якому випадку запускаєте оновлення місцезнаходження, основна структура розташування пропонує користувачеві підтвердити, чи слід повторно ввімкнути служби локації.

Тож не можете просто розпочати оновлення служб визначення місцезнаходження будь-яким способом, щоб викликати сповіщення


15
Це насправді не працює таким чином, і, мабуть, це пов’язано з тонкою різницею між locationServicesEnabled та авторизованими . Якщо їх вимкнено, буде запропоновано ввімкнути, але якщо їх увімкнено, але заборонено, це нічого не зробить. Однак це дуже заплутана документація.
SG1,

locationServicesEnabled - застарілий метод.
Ben Patch

6

Ось швидка реалізація 3 коду, наданого Markus та 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)

5

У Swift 4 є оновлення в його синтаксисі.

Стрімкий 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

Думаю, ви отримаєте відповідь на своє запитання, коли Apple задумається про новий SDK. На даний момент, і наскільки мені відомо, це неможливо:

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

Але ... Коли Карти це роблять, це МОЖЕ зробити, але, ймовірно, за допомогою приватного API. Якщо ви не боїтесь такого роду кодування, то, на мій погляд, вам слід шукати там.


1

Ось швидка версія коду у відповіді Маркуса. Цей код створює попередження, яке дає користувачеві можливість відкрити Налаштування.

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)

1

Стрімкий ,

Як тільки ви вимкнете служби визначення місцезнаходження для програми, методи делегування місцеположення почнуть відображати помилки. Отже, при отриманні помилки ми можемо перевірити, чи ввімкнено / вимкнено служби локації. І відповідно до результату, ми можемо попросити користувача перейти до налаштувань і ввімкнути служби локації.

Додайте перевірку дозволу у своєму методі делегування адміністратора місцезнаходжень на помилку

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

остання швидка версія на основі відповідей вище.

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)
    }

0

Розширення Swift 3 для створення контролера попереджень налаштувань:

імпортний фонд

extension UIAlertController {
    func createSettingsAlertController(title: String, message: String) -> UIAlertController {
        let controller = 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, handler: { action in
            UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
        })
        controller.addAction(cancelAction)
        controller.addAction(settingsAction)

        return controller
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.