Что делает временную авторизацию всегда временной?

Aug 16 2020

Согласно Apple, если вы попросите свое приложение Core Location получить авторизацию Always, когда авторизация «не определена», пользователь увидит диалоговое окно авторизации When In Use, но на самом деле ваше приложение получит авторизацию Always - временно.

Это должно означать, что если вы на самом деле не используете свои способности Always, вы потеряете их, вернувшись к When In Use.

Хорошо, но когда произойдет это возвращение? Кажется, я не могу этого добиться. Мое приложение просто остается с авторизацией «Всегда», хотя пользователь думает, что это авторизация только «Когда используется».

Вот весь код моего тестового приложения (iOS 14):

class ViewController: UIViewController, CLLocationManagerDelegate {
    @IBOutlet weak var label: UILabel!
    
    let locman = CLLocationManager()
    override func viewDidLoad() {
        super.viewDidLoad()
        locman.delegate = self
    }

    @IBAction func doAskForAlways(_ sender: Any) {
        self.checkForLocationAccess(always:true)
    }
    
    func checkForLocationAccess(always:Bool = false, andThen f: (()->())? = nil) {
        let status = self.locman.authorizationStatus()
        switch status {
        case .authorizedWhenInUse:
            if always { // try to step up
                self.locman.requestAlwaysAuthorization()
            } else {
                f?()
            }
        case .authorizedAlways:
            f?()
        case .notDetermined:
            if always {
                self.locman.requestAlwaysAuthorization()
            } else {
                self.locman.requestWhenInUseAuthorization()
            }
        case .restricted:
            break
        case .denied:
            break
        default: fatalError()
        }
    }
    
    fileprivate func updateStatus(_ status: CLAuthorizationStatus) {
        self.label.text = {
            switch status {
            case .authorizedAlways: return "Always"
            case .authorizedWhenInUse: return "When In Use"
            default: return ""
            }
        }()
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        let status = manager.authorizationStatus()
        print("authorization is", status.rawValue)
        updateStatus(status)
    }
    
    @IBAction func doStatus(_ sender: Any) {
        self.updateStatus(self.locman.authorizationStatus())
    }
}

Вам понадобятся две кнопки и этикетка. Нажмите первую кнопку, чтобы запросить авторизацию «Всегда», если у вас нет авторизации для начала («не определено»). Вы увидите диалоговое окно авторизации при использовании. Разрешить авторизацию. Теперь поиграйте с приложением и продолжайте следить за отображением статуса на этикетке. При необходимости вы можете нажать вторую кнопку, чтобы обновить статус.

Проблема в том, что он остается всегда. Когда мое «положение» закончится, и авторизация вернется к «Когда используется»? Как я могу способствовать этому?

Ответы

5 Rob Aug 16 2020 at 04:12

В статье Что нового в основной локации WWDC 2019 описывается основной процесс в iOS 13.0:

  1. Ваше приложение запрашивает разрешение «всегда».

  2. Пользователь видит предупреждение о разрешениях «когда используется», а не предупреждение о разрешениях «всегда»:

  3. Если пользователь разрешает «при использовании», приложение находится в состоянии «всегда временно».

    В этом случае, что несколько сбивает с толку, authorizationStatusзначок вернется, .authorizedAlwaysкогда вы находитесь в этом «временном всегда» состоянии, а приложение «Настройки» на телефоне предложит его в состоянии «когда используется». Но на самом деле он находится в этом состоянии «всегда временно», а не в том, что можно было бы сделать authorizationStatusиз того, что вы видите в приложении «Настройки».

    Излишне говорить, что если пользователь даже не разрешает «когда используется» (например, он отклоняет или выбирает «только один раз»), то очевидно, что вы не будете в состоянии «всегда временно».

  4. Он остается в этом временном состоянии до тех пор, пока, как говорится в видео, вы «не начнете использовать полномочия« всегда »». Например, если вы запускаете услугу значительных изменений и перемещаетесь на расстояние, достаточное для запуска значительного изменения.

    Когда приложение действительно «начинает использовать возможности« всегда »», ОС спросит пользователя, готовы ли они обновить «при использовании» до «всегда». (Это не всегда происходит немедленно, но будет ждать, пока пользователь не будет занят другими делами, чтобы снизить риск того, что он отклонит предупреждение, просто чтобы вернуться к тому, что он делал.)

Так что вопрос не в «возвращении» в какое-то другое состояние. Приложение будет оставаться в этом состоянии «всегда временно» до тех пор, пока не будет заключено окончательное «соглашение» (когда пользователь увидит второе предупреждение и либо согласится на обновление, .authorizedAlwaysлибо откажется от него, и оно будет установлено на .authorizedWhenInUse).


Я знаю, что вы это знаете, но ради будущих читателей:

В видеоролике WWDC 2020 Что нового в локации описывается изменение, внесенное в iOS 13.4. Вместо приведенного выше потока (где вы запрашиваете «всегда», пользователь видит разрешения «при использовании», и они не видят «обновлять до всегда», пока службы «всегда» не будут запущены), в iOS 13.4 был представлен новый поток, где вы можете запросить «когда используется» (а не «всегда») и, если пользователь предоставил это, вы можете запросить «всегда» позже, где это уместно в приложении, и пользователь получит второе предупреждение ( на этот раз с вопросом, хочет ли пользователь перейти на «всегда» или нет). Вам просто нужны соответствующие строки разрешений.