iOS:应用程序在安装应用程序时不会询问用户的权限。 每次都得到kCLAuthorizationStatusNotDetermined – Objective-c&Swift

我正在尝试在iOS应用程序中获取用户位置。 我首先在我的项目中包含了corelocation框架。 然后在一个button上单击我调用核心位置API如下。 当我试图在设备中安装时,核心位置永远不会请求用户权限。 当我尝试获取button上的位置点击,我得到kCLAuthorizationStatusNotDetermined作为authorisationStatus。 请帮助我。 我不知道发生了什么事。

- (IBAction)fetchLessAccurateLocation:(id)sender { [self.txtLocation setText:@""]; locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; locationManager.distanceFilter = 1000; if ([self shouldFetchUserLocation]) { [locationManager startUpdatingLocation]; } } 

这是我的shouldFetchUserLocation方法:

 -(BOOL)shouldFetchUserLocation{ BOOL shouldFetchLocation= NO; if ([CLLocationManager locationServicesEnabled]) { switch ([CLLocationManager authorizationStatus]) { case kCLAuthorizationStatusAuthorized: shouldFetchLocation= YES; break; case kCLAuthorizationStatusDenied: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"App level settings has been denied" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; case kCLAuthorizationStatusNotDetermined: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The user is yet to provide the permission" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; case kCLAuthorizationStatusRestricted: { UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The app is recstricted from using location services." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } break; default: break; } } else{ UIAlertView *alert= [[UIAlertView alloc]initWithTitle:@"Error" message:@"The location services seems to be disabled from the settings." delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; alert= nil; } return shouldFetchLocation; } 

这是我的核心位置委托方法:

 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0){ NSLog(@"location fetched in delegate"); CLLocation* location = [locations lastObject]; NSDate* eventDate = location.timestamp; NSTimeInterval howRecent = [eventDate timeIntervalSinceNow]; if (abs(howRecent) < 15.0) { // If the event is recent, do something with it. NSLog(@"inside loop.... latitude %+.6f, longitude %+.6f\n", location.coordinate.latitude, location.coordinate.longitude); } NSLog(@"latitude %+.6f, longitude %+.6f\n", location.coordinate.latitude, location.coordinate.longitude); [self.txtLocation setText:[NSString stringWithFormat:@"\nlatitude: %+.6f \nlongitude: %+.6f", location.coordinate.latitude, location.coordinate.longitude]]; [locationManager stopUpdatingLocation]; [locationManager stopMonitoringSignificantLocationChanges]; if(locationManager!=nil){ locationManager.delegate= nil; locationManager= nil; } } 

我面临着同样的问题,重新安装我的应用程序后,它是返回kCLAuthorizationStatusNotDetermined每当检查[CLLocationManager authorizationStatus]和应用程序甚至没有出现在设置>隐私>定位服务。

iOS提示用户批准访问位置服务的授权对话框会在[locationManager startUpdatingLocation]上触发,在您的情况下永远不会调用( shouldFetchUserLocation将始终为NO )。

米格尔C.的解决scheme似乎是一个很好的解决办法,将尝试。

编辑iOS8.x

当iOS8来的时候,它在CLLocationManager的使用方式上几乎没有什么变化。 正如其他答案中提到的几次,它需要额外的步骤比较iOS7。 今天我自己面对这个问题,发现这篇文章 (这是从其他多个问题引用,但它完成了我以前的答案)。 希望能帮助到你!

iOS8让我们对LocationsServices进行了主要的API更改

假设[CLLocationManager locationServicesEnabled]返回YES,

随着首次推出的iOS应用程序[iOS7和iOS8] – locationMangers(CLLocationManager)authorizationStatus预设为

 authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined 

在iOS7 +中提示

启动locationManger(CLLocationManager,Strong)并设置委托(CLLocationManagerDelegate)

现在提示用户使用位置服务,并在设置>隐私>位置服务列出应用程序它必须调用任何位置服务方法,它取决于应用程序的要求,例如,如果应用程序是下面的一种

位置更新 – [self.locationManager startUpdatingLocation]

RegionMonitoring – [self.locationManager startMonitoringForRegion:beaconRegion]

在执行上述方法之后,iOS会提示用户请求接受在应用程序中使用位置服务,而不pipe用户select应用程序将在设置>隐私>位置服务下列出。

在iOS8 +中提示

它与iOS8的情况相同,首次启动应用程序位置服务

 authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined 

iOS 8我们有新的方法来向用户显示提示

 [self.locationManager requestAlwaysAuthorization] or [self.locationManager requestWhenInUseAuthorization] 

requestAlwaysAuthorization / requestWhenInUseAuthorization可用于iOS8。 如果应用程序部署目标是iOS7,然后将其包装在if块中以确保在iOS7中这不会导致应用程序崩溃。

 if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [self.locationManager requestAlwaysAuthorization]; . } 

要么

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

很重要 ###:

根据iOS8,它必须包括string,说明为什么应用程序使用requestAlwaysAuthorization / requestWhenInUseAuthorization在info.plist中包括这些属性的任何相应的应用程序的要求

对于kCLAuthorizationStatusAuthorizedAlways包括键/值(string值)对

 NSLocationAlwaysUsageDescription = App use Locations service mode Always 

对于kCLAuthorizationStatusAuthorizedWhenInUse包含键/值(string值)对

 NSLocationWhenInUseUsageDescription = App use Locations service mode In Use 

info.plist的截图(如果有人被这个困惑) 在这里输入图像说明

Objective-C遵循以下的介绍:

iOS-11对于iOS 11有一个看看这个答案: iOS 11的位置访问

需要添加两个键到plist,并提供如下图像消息:

  1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription 

在这里输入图像说明 iOS-10及以下版本:

 NSLocationWhenInUseUsageDescription 

在这里输入图像说明

 locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers; if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){ [locationManager requestWhenInUseAuthorization]; }else{ [locationManager startUpdatingLocation]; } 

委托方法

 #pragma mark - Lolcation Update - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"didFailWithError: %@", error); UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [errorAlert show]; } -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { switch (status) { case kCLAuthorizationStatusNotDetermined: case kCLAuthorizationStatusRestricted: case kCLAuthorizationStatusDenied: { // do some error handling } break; default:{ [locationManager startUpdatingLocation]; } break; } } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *location = [locations lastObject]; userLatitude = [NSString stringWithFormat:@"%f", location.coordinate.latitude] ; userLongitude = [NSString stringWithFormat:@"%f",location.coordinate.longitude]; [locationManager stopUpdatingLocation]; } 

SWIFT代码

按照下面的说明:

iOS-11对于iOS 11有一个看看这个答案: iOS 11的位置访问

需要添加两个键到plist,并提供如下图像消息:

  1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription 

在这里输入图像说明 iOS-10及以下版本:

在这里输入图像说明

 import CoreLocation class ViewController: UIViewController ,CLLocationManagerDelegate { var locationManager = CLLocationManager() //MARK- Update Location func updateMyLocation(){ locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers; if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)){ locationManager.requestWhenInUseAuthorization() } else{ locationManager.startUpdatingLocation() } } 

委托方法

 //MARK: Location Update func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { NSLog("Error to update location :%@",error) } func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { switch status { case .NotDetermined: break case .Restricted: break case .Denied: NSLog("do some error handling") break default: locationManager.startUpdatingLocation() } } func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let location = locations.last! as CLLocation var latitude = location.coordinate.latitude var longitude = location.coordinate.longitude } 

你必须有NSLocationWhenInUseUsageDescription添加到你的info.plist 。 它有点奇怪,但只是把它作为一个string值没有文本,然后当你想要位置开始:

 CLLocationManager * locationManager = [[CLLocationManager alloc] init]; [locationManager requestWhenInUseAuthorization]; 

如果您在iOS8上遇到这个问题,请使用:requestWhenInUseAuthorization。

在iOS 8中,您需要做两件额外的事情才能获得位置信息:向Info.plist添加一个密钥,并请求位置pipe理器授权它开始。 有两个Info.plist密钥用于新的位置授权。 其中一个或两个键是必需的。 如果这两个键都不存在,则可以调用startUpdatingLocation,但位置pipe理器不会实际启动。 它不会发送失败消息给委托(因为它从来没有启动,它不能失败)。 如果您添加一个或两个密钥,但忘记明确请求授权,它也将失败。

所以你需要做的第一件事就是将下面的一个或两个键添加到Info.plist文件中:

 NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription 

这两个键都需要一个string,这是描述为什么你需要位置服务。 您可以input一个string,如“需要find您所在的位置”,如iOS 7中,可以在InfoPlist.strings文件中进行本地化。

接下来,您需要请求相应的位置方法,WhenInUse或Background的授权。 使用这些调用之一:

 [self.locationManager requestWhenInUseAuthorization] [self.locationManager requestAlwaysAuthorization] 

欲了解更多信息 。

自从iOS 7发布以来,我曾经在Rashmi Ranjan mallick的评论中多次提到过这个问题。 我真的认为是来自iOS 7的一个bug,他们在iOS的新版本中有很多。

对我来说,问题是一样的:

打开应用程序,从来没有问过位置。 iOS并没有询问特权
2.我去设置 – >隐私 – >位置服务,我的应用程序不在那里。
3.我无法以任何方式更改我的应用程序的位置权限。

一个解决方法是:

1.杀死你的应用程序。
2.使用主开关button禁用所有位置服务。
3.再次转到您的应用程序。
4.杀死你的应用程序。
5.在上一个开关button上再次启用位置服务。
6.如果仍然没有出现在列表中再次去你的应用程序,再次杀死它,然后回到设置。
现在应该在那里。

这对我有用,我希望这是有用的。

更新:如果iOS 8确定您正在调用requestWhenInUseAuthorizationrequestAlwaysAuthorization

你可以按照这个代码:)

 #ifdef __IPHONE_8_0 if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { if([[Wave_SettingsObject sharedObject] backgroundLocationEnabled].boolValue == YES) { if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription key"); } if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) //iOS 8+ { [locationManager requestAlwaysAuthorization]; } } else if([[Wave_SettingsObject sharedObject] isLocationEnabled].boolValue == YES) { if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { NSLog(@"Info.plist does not contain NSLocationWhenInUseUsageDescription key"); } if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) //iOS 8+ { [locationManager requestWhenInUseAuthorization]; } } } #endif 

卸载应用程序并尝试再次运行。

如果不起作用,请转到设置并禁用该应用程序的授权。 之后,再次运行它,看看它是否要求权限。

要么:

你可以用这样的代码强制应用程序开始监视位置:

 self.locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBest; [locationManager startUpdatingLocation]; 

在你的委托方法中,你可以检测是否有错误获取位置,你可以通知用户。

 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { // Delegate of the location manager, when you have an error NSLog(@"didFailWithError: %@", error); UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"application_name", nil) message:NSLocalizedString(@"location_error", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil]; [errorAlert show]; } 

如果您有任何问题告诉我。

尝试添加

[locationManager startUpdatingLocation]

还要确保位置服务已打开。

编辑:

也请尝试删除应用程序并重新安装它。 可能有一个应用程序正在阅读的logging,这是防止它要求使用位置的许可。

在提示位置时,不要忘记这些事情(iOS 8+):

  1. 在应用的info.plist中添加这个标志:NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription取决于你是否想要总是访问位置或者只有当应用程序正在使用(如果你不需要总是访问,build议使用第二个)。 这是最重要的,因为它是新奇怪的。
  2. 如果您始终请求权限,请不要忘记将位置更新作为背景模式添加到您的目标function上
  3. 确保在初始化位置pipe理器时请求正确的权限:

     -(void)initLocationManager{ locationManager = [[CLLocationManager alloc] init]; locationManager.delegate=self; [locationManager requestAlwaysAuthorization]; // HERE ASK FOR THE RELEVANT } 

为了在模拟器中testing,我build议你从它的选项中“重置所有的内容和设置”。 这是获得应用程序的新用户所获得的完全相同体验的唯一方法。

我碰到这个问题,执行所有必要的事情,包括pList键,我的应用程序仍然没有请求位置。

原来问题是locationManagervariables不能是本地的 – 它需要是一个实例variables。

所以,而不是

 -(void) updateLocation { CLLocationManager *locationManager = ... } 

它需要是:

 CLLocationManager *locationManager; -(void) updateLocation { self.locationManager = ... } 

我有一个类似的问题,但造成了一个不同的原因。 在这里添加它可以帮助其他人。

我停止接收请求授权消息,并且因为它在其他答案中描述的要求已经满足之前工作:plist中的密钥,检查授权状态,然后在ios8 +中请求权限。

在我的情况下,这个问题与“访问指南”模式有关。 这是一个信息亭的应用程序,一旦“访问指南”被激活,它只开始范围信标。 但是在这种模式下,似乎并没有发送授权消息的请求。 我可以解决它只是将请求授权过程移动到第一个显示视图的DidLoad。

使用相机的请求也会发生同样的情况。