代码之家  ›  专栏  ›  技术社区  ›  matt

什么使临时授权总是临时的?

  •  1
  • matt  · 技术社区  · 4 年前

    根据苹果公司的说法,如果你在授权“未确定”时要求你的Core Location应用程序获得Always授权,用户会看到when In Use授权对话框,但事实上你的应用程序暂时获得了Always授权。

    这应该意味着,如果你实际上没有 使用 你的永久权力,你会失去它们,恢复到使用时。

    好吧,但这种逆转什么时候会发生?我似乎无法让它发生。我的应用程序只停留在Always授权状态,即使 用户 认为这只是使用时授权。

    以下是我的测试应用程序(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())
        }
    }
    

    你需要两个按钮和一个标签。当您没有授权时(“未确定”),点击第一个按钮要求始终授权。您将看到“使用时授权”对话框。授予授权。现在,使用该应用程序并继续观看标签中的状态显示。如果需要,您可以点击第二个按钮更新状态。

    问题是它总是停留在Always。我的“规定”何时结束,以便授权恢复为“使用时”?我如何鼓励这种情况发生?

    0 回复  |  直到 4 年前
        1
  •  5
  •   Rob Md Fahim Faez Abir    4 年前

    WWDC 2019 What's New in Core Location ,他们概述了iOS 13.0中的基本流程:

    1. 您的应用程序始终请求权限。

    2. 用户在使用时会看到权限警报,而不是始终权限警报:

      enter image description here

    3. 如果用户在使用时授权,则应用程序始终处于临时状态。

      在这种情况下,有点令人困惑的是 authorizationStatus 会回来的 .authorizedAlways 当你处于这种临时状态时,手机上的“设置”应用程序会建议它处于使用状态。但实际上,它总是处于这种暂时的状态,与人们可能从中推断的不太一样 授权状态 也不是从“设置”应用程序中看到的内容。

      不用说,如果用户在使用时甚至没有授权(例如他们只拒绝或选择了一次),那么很明显你不会处于临时的总是状态。

    4. 它一直处于这种临时状态,直到,正如视频所说,你开始使用永远的权力。例如,如果您启动了重大变更服务,并移动了足以触发重大变更的距离。

      当应用程序开始使用永久电源时,操作系统会询问用户是否愿意在使用时升级为永久电源。(它并不总是立即发生,而是会等到用户不忙于其他事情时,以降低他们为了回到自己正在做的事情而忽略警报的风险。)

      enter image description here

    所以,这不是回到其他国家的问题。应用程序将始终保持这种临时状态,直到达成最终协议(用户看到第二个警报并同意升级到 始终获得授权 或否认,并设置为 .authorizedWhenInUse ).


    我知道你知道这一点,但为了未来的读者:

    WWDC 2020视频 What's new in location ,他们描述了iOS 13.4中引入的一项更改。iOS 13.4引入了一个新的流程,而不是上面的流程(你要求始终,用户看到使用时的权限,在实际触发始终服务之前,他们看不到升级到始终),在这个流程中,你可以要求何时使用(而不是始终),并假设用户授予了它,你可以在应用程序中适当的时候稍后要求始终,然后用户会收到第二个警报(这次询问用户是否想升级到始终或不升级)。您只需要适当的权限字符串。