IOS: 应用程序在安装应用程序时没有要求用户的许可

我试图在我的 iOS 应用程序中获取用户位置。我首先在我的项目中包含了共同定位框架。然后单击一个按钮,我调用核心位置 api,如下所示。当我试图在设备中安装此程序时,核心位置从不询问用户权限。当我尝试在单击按钮时获取位置时,我得到的是 kCLAuthorizationStatusNotDefed 作为 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];
}
}

这是我的 should FetchUserLocation 方法:

-(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;
}
}
90995 次浏览

加一下

[locationManager startUpdatingLocation]

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

编辑:

还可以尝试删除应用程序并重新安装它。可能有一个应用程序正在读取的记录,阻止它请求使用位置的许可。

卸载应用程序并重新运行它。

如果它不工作,去设置和禁用该应用程序的授权。然后再次运行它,看看它是否询问权限。

或者:

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

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];
}

如果你有任何问题,请告诉我。

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

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

米格尔 C 的解决方案似乎是一个很好的解决办法,将尝试这一点。

为 iOS8.x 编辑

当 iOS8出现时,CLLocationManager 的使用方式几乎没有改变。正如在其他答案中几次提到的那样,与 iOS7相比,它需要额外的步骤。今天我亲自面对了这个问题,并找到了这个 文章(它已经从多个其他问题引用,但它完成了我早期的答案)。希望能有帮助!

自从 iOS7发布以来,Rashmi Ranjan Mallick 在评论中几次提到这个问题。我真的认为是 iOS7的一个错误,他们在新版本的 iOS7中有很多这样的错误。

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

1. 打开应用程序,从不询问位置。 iOS 不询问许可
我去设置-> 隐私-> 位置服务,我的应用程序不在那里。
我无法以任何方式更改我的应用程序的位置权限。 < br >

解决办法之一是:

关闭你的应用程序。
2. 用主开关按钮禁用所有定位服务。
3. 再次打开你的应用程序。
4. 关闭你的应用程序。
5. 在上一个切换按钮上再次启用位置服务。
6.如果仍然没有出现在列表中,再次进入应用程序,再次关闭它,然后返回设置。
现在它应该在那里了

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

更新: 如果 IOS8确定您正在调用 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

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

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

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


[locationManager requestWhenInUseAuthorization];

IOS8为我们带来了 LocationsServices 的主要 API 变化

假设 返回是,

随着 iOS 应用程序[ iOS7和 iOS8]的首次推出-locationMangers (CLLocationManager) AuthorizationStatus 预先设定

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

在 iOS7 + 中提示

启动 locationManager (CLLocationManager) ,Strong)并设置委托(CLLocationManagerGenerate)

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

位置更新 -[self.locationManager startUpdatingLocation]

区域监测 -[self.locationManager startMonitoringForRegion:beaconRegion]

在执行上述方法后,iOS 会提示用户要求接受使用应用程序中的位置服务,而不论用户选择的应用程序将列在设置 > 隐私 > 位置服务。

在 iOS8 + 中提示

IOS8也是如此,它首次推出了 App Locations Services

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

IOS8中我们有了新的向用户显示提示的方法

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

RequestAlwaysAuthorization/requestWhenInUseAuthorization 可从 iOS8获得。 如果应用程序部署目标是 iOS7,那么将其包装在 如果块中,以确保在 iOS7中不会导致应用程序崩溃。

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

或者

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

非常重要 # # :

根据 iOS8,必须包含字符串说明为什么应用程序使用 requestAlwaysAuthorization/requestWhenInUseAuthorization 在 info.plist 中,根据应用程序的要求,包含这些属性中的任何一个

始终包含键/值(字符串值)对

NSLocationAlwaysUsageDescription = App use Locations service mode Always

包含键/值(字符串值)对

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use

Plist 的屏幕截图(以防有人对此感到困惑) enter image description here

在 iOS 8中,你需要做两件额外的事情来让位置工作: 向 Info.plist 添加一个密钥,并请求位置管理器授权它启动。有两个用于新位置授权的 Info.plist 键。需要这两个密钥中的一个或两个。如果这两个键都不存在,可以调用 startUpdatingLocation,但位置管理器实际上不会启动。它也不会向委托发送失败消息(因为它从未启动,所以不会失败)。如果您添加了一个或两个密钥,但是忘记显式请求授权,那么它也会失败。

因此,您需要做的第一件事是向 Info.plist 文件添加以下一个或两个键:

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

这两个键都接受一个字符串,该字符串描述了为什么需要位置服务。您可以输入一个类似“ Location is need to find out where You are”的字符串,与 iOS 7一样,这个字符串可以本地化在 InfoPlist.string 文件中。

接下来,您需要请求相应位置方法的授权,使用下列调用之一:

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

对于 更多信息

当提示选择位置时,千万不要忘记这些事情(iOS8 +) :

  1. 在你的应用的 info.plist 上添加这个标志: NSLocationAlwaysUsageDescription 或 NSLocationWhenInUseUsageDescription 取决于你是想总是访问位置还是只在应用正在使用的时候(如果你不需要总是访问,建议使用第二个)。这是最重要的,因为它是新的和奇怪的。
  2. 如果您请求总是权限,不要忘记添加位置更新作为您的目标功能的后台模式
  3. 在初始化位置管理器时,请确保您正在请求正确的许可:

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

For testing in simulator I suggest you to "Reset all content and settings" from it's options. That's the only way to get the exact same experience a new user of the app would get.

我遇到了这个问题,实现了所有必要的东西,包括 pList 键和我的应用程序仍然没有请求位置。

原来问题在于 locationManager 变量不能是本地的——它需要是一个实例变量。

所以

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

它必须是:

CLLocationManager *locationManager;


-(void) updateLocation {
self.locationManager = ...
}

我也有过类似的问题,但原因不同。把它加到这里,以防对其他人有帮助。

我停止接收请求授权的消息,因为它在其他答案中描述的需求已经满足之前就已经工作了: 列表中的键,检查授权状态,然后在 ios8 + 中请求许可。

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

同样的事情也会发生在使用摄像头的请求上。

目标 C 遵循以下说明:

IOS-11 对于 iOS 11来说,看看下面的答案: iOS 11位置访问

需要添加两个键到 plist 并提供如下图所示的信息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription

enter image description here IOS-10及以下版本:

NSLocationWhenInUseUsageDescription

enter image description here

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];
}

快速密码

遵照以下指示:

IOS-11 对于 iOS 11来说,看看下面的答案: iOS 11位置访问

需要添加两个键到 plist 并提供如下图所示的信息:

 1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription

enter image description here IOS-10及以下版本:

enter image description here

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


}