请求用户的iOS位置权限时,我如何知道是否已向用户请求locationManager.requestAlwaysAuthorization()
?
如果用户具有.AuthorizedWhenInUse
状态并且始终授权的请求被拒绝,则不会显示下一个请求的始终身份验证提示,因此我不会收到此请求启动的任何回调。
有什么想法吗?
您需要检查CLLocationManager.authorizationStatus()
并且仅在值.notDetermined
时才请求授权,因为这是实际显示授权提示的唯一情况。
您可以检查授权状态并比较它是否notDetermined
尚未询问,否则 - 是否已询问。
你可以通过使用这样的authorizationStatus()
来知道。
if CLLocationManager.authorizationStatus() == .notDetermined {
print("Not Determined")
}
else if CLLocationManager.authorizationStatus() == .restricted {
print("Restricted")
}
else if CLLocationManager.authorizationStatus() == .denied {
print("Denied")
}
else if CLLocationManager.authorizationStatus() == .authorizedAlways {
print("Always Authorized")
}
else if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
print("Authorized When Require")
}
如果对话框第一次出现,它将返回.notDetermined
状态,并且如果您响应对话框,它将根据您的选择返回状态,例如如果您允许访问您的位置,则始终返回.authorizedAlways
。
经过大量的头脑风暴,我找到了解决方案。
-
每次应用启动时,或在用户查看"设置"应用后应用进入前台时,检查授权状态。
-
如果状态为
notDetermined
,则请求authorizedWhenInUse
。你不能直接跳到authorizedAlways
. -
如果状态为
authorizedWhenInUse
,则请求authorizedAlways
。
如您所知,问题是当用户从notDetermined
转到notDetermined
时,即不会更改其设置。我们需要能够在提示他们之前看到状态。
这实际上很容易,只需将CLLocationManager.authorizationStatus()
的值保存在名为previousAuthStatus
的属性中即可。
private var previousAuthStatus = CLLocationManager.authorizationStatus()
当应用程序进入前台时,检查授权状态与以前的状态。
完整代码
不要错过设置previousAuthStatus
的最后一点
func checkStatus(_ status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
// request "When in use"
locationManager.requestWhenInUseAuthorization()
case .authorizedWhenInUse:
// already tried requesting "Always"?
guard previousAuthStatus != .authorizedWhenInUse else {
<#notify the user...#>
break
}
// otherwise, request "Always"
locationManager.requestAlwaysAuthorization()
case .authorizedAlways:
// start updating location
<#dismiss any warning you may have displayed#>
locationManager.startUpdatingLocation()
case .denied:
<#notify the user...#>
case .restricted:
<#notify the user...#>
@unknown default:
break
}
// save status for next check
previousAuthStatus = status
}
我面临着同样的问题。这仅对于应用程序更新(在以前版本中未将 authStatus 存储在 UserDefaults 中)不是问题。如果用户决定卸载并重新安装应用程序(删除用户默认值),或者用户手动将状态从"始终"更改为"使用时"(无法知道它已更改为"使用时"或是否一直都是该状态),这也是一个问题。
顺便说一句:用户手动更改授权实际上很常见,因为 iOS 现在每隔一段时间就会发出警报"AppName 一直在后台使用您的位置......你想继续允许这个吗"(或类似的东西不记得了)。我的许多用户在该警报中选择"否",导致"始终"位置访问更改为"使用时",而应用程序没有收到有关该通知的通知。
但是,iOS确实记得之前是否已经问过requestAlwaysAccess
,无论如何。即使在卸载并重新安装应用程序后。
因此,由于缺乏其他选项,我现在正在使用它,老实说,它不是最用户友好的,但它确实有效并且用户友好"足够"(至少对我来说)。
我只是发出一个警报,其中一个按钮指向应用程序的设置页面,用户可以在其中手动更改设置,而不是请求始终授权。如果应用程序之前显示此警报,我确实添加了用户默认存储。如果是这样,我不会再展示它。
switch CLLocationManager.authorizationStatus() {
case .restricted, .denied:
// show an alert with one button opening settings (see below)
case .authorizedAlways:
// already have always permission, continue with your code
case .notDetermined:
// request whenInUse authorisation (you can request always authorisation here too, but iOS won't show 'always' as a choice the first time)
case .authorizedWhenInUse:
guard !UserDefaults.showedNoAlwaysAuthorisationAlert else {
return
}
UserDefaults.showedNoAlwaysAuthorisationAlert = true
// show the alert with "no thanks" and "settings" button
// button action:
if 'settingsButtonTapped', let settingsUrl = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: nil)
}
}