在我的应用程序中,我有一个名为" Discover"的标签。 “发现”标签将使用用户的当前位置来查找" stuff"靠近他们。我没有向用户提供通用的授权请求(通常会根据研究得到拒绝),而是向用户提供一个解释我们要求的模式。如果他们说是,则会弹出实际的授权消息。
但是,用户仍然可以选择不提示。有没有办法在提示中添加回调,以便用户选择一个选项后我可以看到他们是否接受或拒绝了?
我试过这个:
func promptForLocationDataAccess() {
locationManager.requestWhenInUseAuthorization()
println("test")
}
正如所料," println"在请求提示出现的同时执行,所以我无法这样做。
问题在于,如果用户选择不使用位置数据,则所提供的内容将与他们接受的内容不同。
理想情况下,我希望能够进行某种回调,但此时我会采取任何合理的方向!
答案 0 :(得分:47)
你可以使用
locationManager:didChangeAuthorizationStatus:
CLLocationManagerDelegate
方法作为各种“回调”。
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusDenied) {
// The user denied authorization
}
else if (status == kCLAuthorizationStatusAuthorized) {
// The user accepted authorization
}
}
在Swift中(用户Michael Marvick建议更新,但出于某种原因拒绝了......):
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.denied) {
// The user denied authorization
} else if (status == CLAuthorizationStatus.authorizedAlways) {
// The user accepted authorization
}
}
答案 1 :(得分:6)
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.denied) {
// The user denied authorization
} else if (status == CLAuthorizationStatus.authorizedAlways) {
// The user accepted authorization
}
}
答案 2 :(得分:5)
当位置的授权状态发生变化时,将调用委托方法didChangeAuthorizationStatus:
。
安装应用后第一次调用requestWhenInUseAuthorization
时,将调用状态为kCLAuthorizationStatusNotDetermined
(0)的委托方法。
如果用户拒绝了位置服务访问权限,则将再次调用委托方法,状态为kCLAuthorizationStatusDenied
(2)。
如果用户批准了位置服务访问权限,则将再次调用委托方法,状态为kCLAuthorizationStatusAuthorizedAlways
(3)或kCLAuthorizationStatusAuthorizedWhenInUse
(4),具体取决于所请求的权限。
在您的应用的后续执行中,根据当前的位置服务权限,调用kCLAuthorizationStatusDenied
后,委托方法将收到状态kCLAuthorizationStatusAuthorizedAlways
或kCLAuthorizationStatusAuthorizedWhenInUse
/ requestWhenInUseAuthorization
设备设置中的应用程序。
答案 3 :(得分:4)
此解决方案在所有情况下都不是最好的,但它对我有用,所以我想我会分享:
import Foundation
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate {
static let sharedInstance = LocationManager()
private var locationManager = CLLocationManager()
private let operationQueue = OperationQueue()
override init(){
super.init()
//Pause the operation queue because
// we don't know if we have location permissions yet
operationQueue.isSuspended = true
locationManager.delegate = self
}
///When the user presses the allow/don't allow buttons on the popup dialogue
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
//If we're authorized to use location services, run all operations in the queue
// otherwise if we were denied access, cancel the operations
if(status == .authorizedAlways || status == .authorizedWhenInUse){
self.operationQueue.isSuspended = false
}else if(status == .denied){
self.operationQueue.cancelAllOperations()
}
}
///Checks the status of the location permission
/// and adds the callback block to the queue to run when finished checking
/// NOTE: Anything done in the UI should be enclosed in `DispatchQueue.main.async {}`
func runLocationBlock(callback: @escaping () -> ()){
//Get the current authorization status
let authState = CLLocationManager.authorizationStatus()
//If we have permissions, start executing the commands immediately
// otherwise request permission
if(authState == .authorizedAlways || authState == .authorizedWhenInUse){
self.operationQueue.isSuspended = false
}else{
//Request permission
locationManager.requestAlwaysAuthorization()
}
//Create a closure with the callback function so we can add it to the operationQueue
let block = { callback() }
//Add block to the queue to be executed asynchronously
self.operationQueue.addOperation(block)
}
}
现在,每当您想要使用位置信息时,只需将其包围:
LocationManager.sharedInstance.runLocationBlock {
//insert location code here
}
因此,每当您尝试使用位置信息时,都会检查授权状态。如果您还没有权限,它会请求权限并等待用户按下“允许”按钮或“不允许”按钮。如果按下“允许”按钮,任何位置数据请求都将在不同的线程上处理,但如果按下“不允许”按钮,则所有位置请求都将被取消。
答案 4 :(得分:0)
目标C
对于didChangeAuthorizationStatus上的块回调,请在 .h
中添加@property void(^authorizationCompletionBlock)(BOOL);
并在 .m
中关注-(void)locationManager:(CLLocationManager *)locationManager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
_authorizationStatus = status;
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorizedWhenInUse:
if (self.authorizationCompletionBlock) {
self.authorizationCompletionBlock(YES); // this fires block
}
default:
if (self.authorizationCompletionBlock) {
self.authorizationCompletionBlock(NO); // this fires block
}
break;
}
}
并添加这样的处理程序:
// this listens block
// in your VC or Utility class
authorizationCompletionBlock = ^(BOOL isGranted) {
completionBlock(isGranted);
};
Swift 3.2
var authorizationCompletionBlock:((Bool)->())? = {_ in}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch (status)
{
case (.authorizedWhenInUse):
if authorizationCompletionBlock != nil
{
authorizationCompletionBlock!(true)
}
default:
if authorizationCompletionBlock != nil
{
authorizationCompletionBlock!(false);
}
}
}
和像这样的处理程序
authorizationCompletionBlock = { isGranted in
print(isGranted)
}
答案 5 :(得分:0)
类似于上述tdon的响应,我创建了一个带有完成块的函数,用于在从设备中检索到状态后传达状态:
func retrieveAuthorizationStatus(completion: @escaping (TrackingState) -> ()) {
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedWhenInUse:
completion(.off)
default:
completion(.issue)
}
}
TrackingState是一个单独的枚举,我正在使用它来管理视图控制器中的显示。您可以轻松地在完成代码块中传递authorizationStatus():
func retrieveAuthorizationStatus(completion: @escaping (CLAuthorizationStatus) -> ()) {
let status = CLLocationManager.authorizationStatus()
completion(status)
}