iOS 8中CLLocationManager的授权问题

16

我正在开发一段针对iOS 8的Swift代码,我试图做与位置相关的事情,因此我在我的Swift视图控制器文件中实现了以下内容:

let locationManger:CLLocationManager = CLLocationManager()

这行代码是为了创建一个CLLocationManager实例以便获取设备的地理位置。

var speedReceived:Double = 0

override func viewDidLoad() {
    super.viewDidLoad()
    locationManger.delegate = self
    locationManger.desiredAccuracy = kCLLocationAccuracyBest
    let authstate = CLLocationManager.authorizationStatus()
    if(authstate == CLAuthorizationStatus.NotDetermined){
       println("Not Authorised")  
      locationManger.requestWhenInUseAuthorization()
    }
    // Do any additional setup after loading the view, typically from a nib.
}

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
    var location:CLLocation = locations[locations.count - 1] as CLLocation
    if(location.horizontalAccuracy > 0){
        self.speedReceived = location.speed
        println(self.speedReceived)
    }
}

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
   println("Couldn't get your location")
}

然而,我似乎无法让这段代码正常工作。它不能保存我的位置使用偏好设置,甚至不提示我允许访问位置。我已经尝试更新我的info.plist文件,但它没有起作用。顺便说一下,如果我在模拟器的隐私设置中选择“始终”,那么如果我立即切换回应用程序,它就可以工作。有人能帮忙吗?我确定这是问题所在,因为我的控制台上显示“未经授权”。任何帮助?

你说你已经更新了你的info.plist - 你是否仔细检查了你的条目?"NSLocationWhenInUseUsageDescription"需要出现,并附有描述你使用位置的字符串。一个简单的拼写错误会阻止你的应用程序提示位置访问。此外,你应该始终调用locationManager.requestWhenInUseAuthorization(),而不仅仅是在你的状态未经授权时。 - Paulw11
6个回答

28
这是一个与iOS 8相关的问题。您需要在您的`.plist`文件中添加NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription键(值可以是将显示在位置提示中的附加消息)。这些键在iOS 8中是必需的。
按照苹果指南的说法:
“当您使用CLLocationManager类的requestAlwaysAuthorization方法请求对位置服务的授权时,需要此密钥。如果此密钥不存在并且您调用requestAlwaysAuthorization方法,则系统会忽略您的请求并阻止应用程序使用位置服务。”

7

我曾经遇到类似的问题,即使在plist中添加了NSLocationAlwaysUsageDescription / NSLocationWhenInUseUsageDescription键,问题仍然存在。

最终,我在plist中添加了“隐私 - 位置使用说明”键,并且好了! 在它起作用一次后,我能够从plist中删除“隐私 - 位置使用说明”键,并继续成功地请求授权。


4

iOS 8改变了位置授权策略。具有向后兼容性的解决方案:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

提醒:在您的Info.plist文件中设置NSLocationWhenInUseUsageDescription关键字。

2

由于我不喜欢直接编辑plist,所以我总是使用UI授予权限。

enter image description here

在用户授予权限的弹出窗口中,显示了荷兰语文本“需要访问权限”和“必须访问权限”。您可以将其更改为任何您喜欢的文本。

只需添加到plist源代码中即可。

<key>NSLocationAlwaysUsageDescription</key>
<string>To get location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>To get location</string>

2

我遇到了完全相同的问题。

记录一下,这不是官方答案。第一个答案是正确的。我只想添加一个FOSS(Objective-C)项目的链接,以说明如何解决。

正如所述,我必须添加该密钥。我的应用程序不需要在后台运行,因此我将NSLocationWhenInUseUsageDescription键添加到了我的info.plist中。

如果您将字符串作为此键的值添加(可选-存在该键足以设置栏),则该字符串将显示在授权弹出窗口中。

然后,我在所有我的[CLLocationManager startUpdating]调用之前添加了以下代码:

if ( [locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)] )
{
    [locationManager requestWhenInUseAuthorization];
}

respondsToSelector是重要的,因为它只在iOS 8中可用。

第一次调用时会显示提醒。之后,它就会跳过。

请注意,我调用了requestWhenInUseAuthorization

它必须与我在plist中放置的值匹配。我想你可以都放,但我不知道。我不需要这样做。

该项目位于此处。大部分工作(不多)都在BMLTAppDelegate.m文件中。

这是一个令人不愉快的惊喜。许多人不知道他们的应用程序将在iOS 8中停止工作。他们将执行与我最初执行的相同操作:在模拟器中快速运行,注意到挂起,并把它归咎于beta漏洞。

现在,我有了另一个问题:所有我的应用程序都已修复,但当我尝试上传应用程序到App Store时,Xcode会崩溃。我在RADAR上已经提出了这个问题。

Xcode 6有点不太稳定。我希望很快就会发布补丁。


1

对于Swift 2,我已经用iOS版本检查替换了respondsToSelector()检查。虽然不够优雅,但这是为了让Xcode 7不出现0错误、0警告所必需的。

if #available(iOS 8.0, *) {
    locationManager.requestWhenInUseAuthorization()
} else {
    locationManager.startUpdatingLocation()
}

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