如何在iOS应用中强制“始终”进行位置访问

问题描述

我正在构建的应用需要始终具有位置访问权限才能正常运行。该应用程序基本上会跟踪位置,并将其放在地图和其他内容上(细节并不重要,哈哈)。

我的目标是:

  1. 提示用户启用“始终”位置访问权限
  2. 如果始终要求访问位置,但用户拒绝,则使该应用程序不可用-基本上只显示一个小按钮,即可将其重定向到可以更改该设置的设置。

我的AppDelegate.swift正在实现CLLocationManagerDelegate,代码如下:

alreadyRequestedLocationWhenInUse = UserDefaults.standard.bool(forKey: "alreadyRequestedLocationWhenInUse")
alreadyRequestedLocationAlways = UserDefaults.standard.bool(forKey: "alreadyRequestedLocationAlways")

        func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
      
        switch CLLocationManager.authorizationStatus() {
        case .notDetermined:
            if (!alreadyRequestedLocationWhenInUse) {
                print("Requesting location access 'while in use'.")
                self.locationManager.requestWhenInUseAuthorization();
                UserDefaults.standard.set(true,forKey: "alreadyRequestedLocationWhenInUse")
                alreadyRequestedLocationWhenInUse = true
            } else {
                prompttochangeLocationSettings()
            }
        case .restricted,.denied:
            print("No Location access")
            prompttochangeLocationSettings()
            break;
        case .authorizedWhenInUse:
            if (!alreadyRequestedLocationAlways) {
                print("Requesting location access 'Always'.")
                self.locationManager.requestAlwaysAuthorization()
                UserDefaults.standard.set(true,forKey: "alreadyRequestedLocationAlways")
                alreadyRequestedLocationAlways = true
            } else {
                prompttochangeLocationSettings()
            }
            break;
        case .authorizedAlways:
            self.startLocationMonitoring();
            break;
        default:
            self.locationManager.requestAlwaysAuthorization();
            return
        }
    }

其中hintTotochangeLocationSettings()是可以正常工作的功能,可将用户带到我的应用程序的设置页面

问题在于,直到他们退出应用程序并返回时,系统不会提示用户启用“始终位置跟踪”。他们被要求获得“使用中”权限(我知道它的工作方式是必须首先对它说“是”),但是我希望始终提示总是马上发生!理论上,在授予“使用时”授权后,应该再次调用locationManagerDidChangeAuthorization函数,但这不会发生!为什么不会发生这种情况?相反,在用户收到询问他们是否要启用“始终”位置访问的小提示之前,会运行hintUsertochangeLocationSettings()并使其无法使用。

有人可以帮我解决这个问题吗? 顺便说一句,我正在使用UserDefaults来跟踪我们是否已完成位置许可请求(因为该请求只能执行一次)。

解决方法

关于此流程的一些观察结果,我们首先请求“在使用中”,然后在获得许可时才请求“始终”(如WWDC 2020 What's New in Location中所述):

  1. 确保在设备而不是模拟器上运行它。使用模拟器时,您可能看不到随后的“在使用中”升级为“始终””权限警报。

  2. 此功能在iOS 13.4中引入。确保您不在较早的iOS 13版本上尝试这样做。在那些较早的版本上,您将不会看到第二个警报升级到“始终”。

  3. 请确保您在代码库中的其他地方没有挥之不去的requestAlwaysAuthorization,这可能会使该应用程序处于“始终临时”状态。进入临时状态后,您将被锁定在13.0的临时流程中。


我知道这不是您想要的,但是为了将来的读者,上述的替代方法是iOS 13.0中引入的更简单的“ provisional always”流程(在WWDC 2019的{{3}中概述})。您只需致电requestAlwaysAuthorization(就不会致电requestWhenInUseAuthorization)。 Apple的目的是让用户更好地了解正在发生的事情,在应用程序使用时显示“使用中”警报,并在应用程序未运行时使用位置服务时自动显示“始终”升级警报。

,

这是一个解决方案,得到了我想要的结果: 首先:在AppDelegate.swift didFinishLaunchingWithOptions函数中调用locationManagerDidChangeAuthorization(locationManager)。我也在applicationWillEnterForeground中调用了它,以便每次打开应用程序时都会重新检查。

第二,这是我的新locationManagerDidChangeAuthorization函数。只需删除return / break语句,但在忘记之前我要立即回答:

func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
  
    switch CLLocationManager.authorizationStatus() {
    case .notDetermined:
        UserDefaults.standard.set(false,forKey: "alreadyRequestedAlwaysLocationAccess")
        alreadyRequestedAlwaysLocationAccess = false
        DispatchQueue.main.async{
            self.coreLocationManager.requestWhenInUseAuthorization()
            self.locationManagerDidChangeAuthorization(manager)
        }
        break;
    case .restricted,.denied:
        print("No Location access")
        promptToChangeLocationSettings()
        break;
    case .authorizedWhenInUse:
        if (!alreadyRequestedAlwaysLocationAccess) {
            print("Requesting location access 'Always'.")
            UserDefaults.standard.set(true,forKey: "alreadyRequestedAlwaysLocationAccess")
            alreadyRequestedAlwaysLocationAccess = true

            DispatchQueue.main.async{
                self.coreLocationManager.requestAlwaysAuthorization()
                self.locationManagerDidChangeAuthorization(manager)
            }
        } else {
            promptToChangeLocationSettings()
        }
        break;
    case .authorizedAlways:
        self.startLocationMonitoring();
        break;
    default:
        return
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...