定位权限问题 iOS 11 和 iOS 10。

18

当我使用iOS11时,请求用户位置权限时出现问题,我的info.plist文件包含:

<key>NSLocationWhenInUseUsageDescription</key>
<string>When in use permissions</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>always permissions</string>
<key>NSLocationAlwaysAndWhenInUsageDescription</key>
<string>Always and in usage permissions</string>

我有两张地图,一张是给客户用的,另一张是给员工用的。对于员工,即使应用程序未运行或在后台运行(他们可以在退出时关闭),我也需要知道他们的位置并请求权限: locationManager.requestAlwaysAuthorization()
对于客户,我只需要在应用程序使用期间获取位置,并请求权限: locationManager.requestWhenInUseAuthorization()
在iOS 11中,这仅在使用期间请求权限,而永久权限则永远不会请求。
在iOS 10中,它具有正确的行为方式。
我想要的行为如下: 当他们是客户(未登录)时,它仅请求在使用期间的权限。如果他们登录(成为员工),即使不在使用期间,也会请求位置。
如果有人能解释一下我错过了/做错了什么,那将非常感谢。
需要注意的是,如果我删除 NSLocationAlwaysUsageDescription 权限,则 iOS10 和 iOS11 都存在同样没有请求永久权限的问题。
还需要补充一点说明。 我已经实现了 didChangeAuthorization 委托功能,并且当用户从调用 requestWhenInUseAuthorization() 的警告中允许权限时,它会被调用。 但是,当我在位置管理器上调用 requestWhenInUseAuthorization() 函数时,委托方法没有被调用,就像它从未接收到该调用一样,用户也不会看到任何警告对话框。

你在真机上测试了吗?还有,你在locationupdate和locationmanager代理方法上设置了断点吗? - Himanshu Moradiya
是的,在两个真实设备上进行测试,一个是运行iOS 10.3.3的iPhone 5,另一个是运行iOS 11的iPhone 6。我在位置管理器委托函数didChangeAuthorization和didUpdateLocations中有日志记录。当应用在前台时,会调用位置信息,但在请求使用权限时并不总是调用更改授权。 - Ben Avery
{btsdaf} - Alok
4个回答

12

我通过创建一个只要求权限的快速独立应用程序来找到了问题,我收到了一个错误日志,指出我使用的密钥是错误的。

我使用了NSLocationAlwaysAndWhenInUsageDescription而不是NSLocationAlwaysAndWhenInUseUsageDescription,这很奇怪,因为从文档中可以看出,应该使用NSLocationAlwaysAndWhenInUsageDescription。纠正后,问题得到了解决,现在iOS 11和10的权限功能按预期正常工作。

感谢您的所有帮助。


可以运行,但你说得对,它肯定与文档不匹配! - Shayne

8
在您的info.plist文件中添加以下内容:
<key>NSLocationUsageDescription</key>
<string></string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>

现在在您的Swift文件中,请不要忘记添加代理:CLLocationManagerDelegate

在您的viewDidLoad()中添加以下内容:

locationManager = CLLocationManager()

locationManager.delegate = self

locationManager.requestWhenInUseAuthorization()

locationManager.desiredAccuracy = kCLLocationAccuracyBest

locationManager.startUpdatingLocation()

locationManager.startMonitoringSignificantLocationChanges()

// Here you can check whether you have allowed the permission or not.

if CLLocationManager.locationServicesEnabled()
    {
        switch(CLLocationManager.authorizationStatus())
        {

        case .authorizedAlways, .authorizedWhenInUse:

            print("Authorize.")

            break

        case .notDetermined:

            print("Not determined.")

            break

        case .restricted:

            print("Restricted.")

            break

        case .denied:

            print("Denied.")
        }
    }

3
不幸的是,对于iOS 11而言,这不是问题,它需要NSLocationAlwaysAndWhenInUsageDescription。请参考以下链接了解如何选择位置服务的授权级别和请求始终授权:https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services/request_always_authorization - Ben Avery
2
在 Swift 的 switch case 中,你不需要使用 break。 - Cesare
@Cesare 我的背景是C#和Java。谢谢你指出来。哈哈 :) - Akhil Nair

1

对于两种情况,客户和员工,您首先需要调用 locationManager.requestWhenInUseAuthorization()

然后,仅在他们是员工的情况下,添加一个调用 locationManager.requestAlwaysAuthorization()

参见https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services/request_always_authorization

概述 要配置位置服务的始终授权,请执行以下操作:向 Info.plist 文件添加 NSLocationWhenInUseUsageDescription 键和 NSLocationAlwaysAndWhenInUsageDescription 键。(在 Info.plist 编辑器中,Xcode 将这些键显示为“隐私 - 使用时定位描述”和“隐私 - 始终使用和使用时定位描述”。) 如果您的应用支持 iOS 10 及更早版本,请将 NSLocationAlwaysUsageDescription 键添加到 Info.plist 文件中。(在 Info.plist 编辑器中,Xcode 将此键显示为“隐私 - 始终定位描述”。) 创建并配置您的 CLLocationManager 对象。最初调用 requestWhenInUseAuthorization() 以启用您的应用程序的基本位置支持。仅在使用需要该级别授权的服务时才调用 requestAlwaysAuthorization() 方法。

当应用程序打开时,每个人都被视为客户,并调用locationManager.requestWhenInUseAuthorization()。一旦他们登录,它会请求locationManager.requestAlwaysAuthorization()。我的理解是,只要我在某个时候进行了使用时请求,我就应该能够在任何后续时刻进行始终跟踪请求。这是正确的吗,还是我误解了? - Ben Avery
是的,这是正确的。 一些愚蠢的问题-1.您是否尝试从iPhone中删除该应用并重新安装它?如果没有,请尝试清理项目,删除应用然后重新安装它。 2.检查您的系统设置-用户可以在系统设置中禁用位置服务,可以为您的应用程序特定地或为所有应用程序禁用它。 - Witterquick
  1. 我试过安装/卸载。
  2. 我检查了我的系统设置,iOS11上没有一直权限,不确定是否有帮助。谢谢你的帮助。
- Ben Avery
@BenAvery,我相信你可以在不调用whileInUseFirst的情况下始终调用alwaysInUse。区别在于,如果您首先请求whileInUse,您可以通过系统提示请求升级为alwaysInUse。但是,如果您首先请求alwaysInUse并且用户不接受,则失去了通过系统提示请求升级的任何能力。 - JustinM

-1

**Swift 5.1 最新可用代码:**

Plist:添加条目

<key>NSLocationWhenInUseUsageDescription</key>
  <string>Needs Location when in use</string>


import UIKit
import CoreLocation

class ViewController: UIViewController {
    var locationManager: CLLocationManager?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager = CLLocationManager()
        
        //Make sure to set the delegate, to get the call back when the user taps Allow option
        locationManager?.delegate = self
    }
}

extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            print("not determined - hence ask for Permission")
            manager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            print("permission denied")
        case .authorizedAlways, .authorizedWhenInUse:
            print("Apple delegate gives the call back here once user taps Allow option, Make sure delegate is set to self")
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接