iOS:应用程序在安装应用程序时未征得用户许可。每次都获得 kCLAuthorizationStatusNotDetermined - Objective-c & Swift
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20664928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS: App is not asking user's permission while installing the app. getting kCLAuthorizationStatusNotDetermined every time - Objective-c & Swift
提问by Rashmi Ranjan mallick
I am trying to fetch user location in my iOS app. I have included corelocation framework in my project first. Then on a button click I am invoking the core location api as below. When I am trying to install this in a device, the core location never asks the user permission. When I try to fetch the location on button click, I am getting kCLAuthorizationStatusNotDetermined as the authorisationStatus. Please help me in this. I have no clue what is happening.
我正在尝试在我的 iOS 应用中获取用户位置。我首先在我的项目中包含了核心定位框架。然后单击按钮,我正在调用核心位置 api,如下所示。当我尝试在设备中安装它时,核心位置从不询问用户许可。当我尝试在单击按钮时获取位置时,我将 kCLAuthorizationStatusNotDetermined 作为授权状态。请帮助我。我不知道发生了什么。
- (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];
}
}
This is my shouldFetchUserLocation method:
这是我的 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;
}
Here is my core location delegate method:
这是我的核心位置委托方法:
- (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;
}
}
采纳答案by David Jirman
I was facing the same issue, after re-installing my app it was returning kCLAuthorizationStatusNotDetermined
whenever checking for [CLLocationManager authorizationStatus]
and the app didn't even show up in Settings > Privacy > Location Services.
我遇到了同样的问题,在重新安装我的应用程序后,它在kCLAuthorizationStatusNotDetermined
每次检查时都会返回,[CLLocationManager authorizationStatus]
并且该应用程序甚至没有出现在“设置”>“隐私”>“定位服务”中。
The authorization dialog that iOS prompts user to approve access to location services is triggered on [locationManager startUpdatingLocation]
which in your case is never called (shouldFetchUserLocation
will be always NO
).
iOS 提示用户批准访问位置服务的授权对话框被触发[locationManager startUpdatingLocation]
,在您的情况下永远不会调用(shouldFetchUserLocation
将始终NO
)。
Miguel C.'s solution seems like a good fix, will try that.
Miguel C. 的解决方案似乎是一个很好的解决方案,会尝试一下。
Edit for iOS8.x
为 iOS8.x 编辑
When iOS8 came it brought little change in the way CLLocationManager is used. As mentioned few times in other answers it requires additional step comparing to iOS7. Today I faced the issue myself and found this article(it's been referenced from multiple other questions but it completes my earlier answer). Hope it helps!
当 iOS8 出现时,它对 CLLocationManager 的使用方式几乎没有改变。正如在其他答案中多次提到的,与 iOS7 相比,它需要额外的步骤。今天我自己遇到了这个问题并找到了这篇文章(它已被多个其他问题引用,但它完成了我之前的回答)。希望能帮助到你!
回答by Rithesh Rao
iOS8 has got us major API changes with the LocationsServices
iOS8 对 LocationsServices 进行了重大的 API 更改
Assuming
[CLLocationManager locationServicesEnabled]
return YES,
假设
[CLLocationManager locationServicesEnabled]
返回YES,
With the First Launch of the iOS App [both iOS7 and iOS8] - locationMangers(CLLocationManager) authorizationStatus preset to
随着 iOS 应用的首次发布 [iOS7 和 iOS8] - locationMangers(CLLocationManager) authorizationStatus 预设为
authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined
Prompting in iOS7+
在 iOS7+ 中提示
Initiate the locationManger (CLLocationManager , Strong) and set the delegates(CLLocationManagerDelegate)
启动locationManger(CLLocationManager,Strong)并设置delegate(CLLocationManagerDelegate)
Now to prompt the user to use Locations Services and List the App under the Settings> Privacy> Locations Services its MUST to call any of the Locations Services Methods, its depends on the App requirement- for example if app is kind of one of the below
现在提示用户使用位置服务并在“设置”>“隐私”>“位置服务”下列出应用程序,它必须调用任何位置服务方法,这取决于应用程序要求 - 例如,如果应用程序是以下之一
Locations Updates - [self.locationManager startUpdatingLocation]
地点更新 - [self.locationManager startUpdatingLocation]
RegionMonitoring - [self.locationManager startMonitoringForRegion:beaconRegion]
区域监控 - [self.locationManager startMonitoringForRegion:beaconRegion]
right after executions of the above method iOS will prompt user requesting to accept use of Locations Services in app and irrespective of user choice app will be listed under the Settings > Privacy > Locations Services.
执行上述方法后,iOS 会立即提示用户请求接受在应用中使用定位服务,无论用户选择何种应用,都将在“设置”>“隐私”>“定位服务”下列出。
Prompting in iOS8+
在 iOS8+ 中提示
Its in same case with iOS8, with the first launch the App Locations Services
与 iOS8 相同,首次启动应用位置服务
authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined
iOS 8 we got new methods for showing prompt to user
iOS 8 我们获得了向用户显示提示的新方法
[self.locationManager requestAlwaysAuthorization]
or
[self.locationManager requestWhenInUseAuthorization]
requestAlwaysAuthorization/requestWhenInUseAuthorization availbable from iOS8. if App deployment target is iOS7 then wrap this under ifblock to make sure in iOS7 this doesn't lead to app crash.
requestAlwaysAuthorization/requestWhenInUseAuthorization 可从 iOS8 获得。如果应用程序部署目标是 iOS7,则将其包装在if块下以确保在 iOS7 中这不会导致应用程序崩溃。
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
{
[self.locationManager requestAlwaysAuthorization]; .
}
or
或者
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
Very Important ###:
很重要 ###:
As per iOS8 its mandatory to include the string stating why app uses requestAlwaysAuthorization/requestWhenInUseAuthorization In info.plist include any of these property respective to the requirement of the app
根据 iOS8,它必须包含说明应用程序为何使用 requestAlwaysAuthorization/requestWhenInUseAuthorization 的字符串在 info.plist 中包含与应用程序要求相关的任何这些属性
for kCLAuthorizationStatusAuthorizedAlways include Key/Value(string Value) pair
对于 kCLAuthorizationStatusAuthorizedAlways 包括键/值(字符串值)对
NSLocationAlwaysUsageDescription = App use Locations service mode Always
for kCLAuthorizationStatusAuthorizedWhenInUse include Key/Value(string Value) pair
对于 kCLAuthorizationStatusAuthorizedWhenInUse 包含键/值(字符串值)对
NSLocationWhenInUseUsageDescription = App use Locations service mode In Use
Screenshot of info.plist (in case anybody is confused by this)
回答by Alok
Objective-CFollow the below intructions:
Objective-C遵循以下说明:
iOS-11For iOS 11 have a look into this Answer: iOS 11 location access
iOS-11对于 iOS 11,请查看此答案:iOS 11 位置访问
Need to Add two Keys into plist and provide message as below image:
需要将两个密钥添加到 plist 并提供如下图所示的消息:
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
NSLocationWhenInUseUsageDescription
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
[locationManager requestWhenInUseAuthorization];
}else{
[locationManager startUpdatingLocation];
}
Delegat Methods
委托方法
#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 Code
SWIFT代码
Follow the below instructions:
请按照以下说明操作:
iOS-11For iOS 11 have a look into this Answer: iOS 11 location access
iOS-11对于 iOS 11,请查看此答案:iOS 11 位置访问
Need to Add two Keys into plist and provide message as below image:
需要将两个密钥添加到 plist 并提供如下图所示的消息:
1. NSLocationAlwaysAndWhenInUseUsageDescription
2. NSLocationWhenInUseUsageDescription
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()
}
}
Delegate Methods
委托方法
//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
}
回答by LemonandlIme
You must have NSLocationWhenInUseUsageDescription
added to you're info.plist
. Its a bit weird but just add it as a string value with no text and then when you want location start with:
你一定已经NSLocationWhenInUseUsageDescription
添加到你了info.plist
。它有点奇怪,但只需将其添加为没有文本的字符串值,然后当您想要位置开始时:
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
[locationManager requestWhenInUseAuthorization];
回答by Abhilash Gopal
If you face this issue on iOS8, please use :requestWhenInUseAuthorization.
如果您在 iOS8 上遇到此问题,请使用:requestWhenInUseAuthorization。
回答by Mohammed Ebrahim
In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start. There are two Info.plist keys for the new location authorization. One or both of these keys is required. If neither of the keys are there, you can call startUpdatingLocation but the location manager won't actually start. It won't send a failure message to the delegate either (since it never started, it can't fail). It will also fail if you add one or both of the keys but forget to explicitly request authorization.
在 iOS 8 中,你需要做两件额外的事情来让定位工作:向你的 Info.plist 添加一个密钥,并请求定位管理器的授权,要求它启动。新位置授权有两个 Info.plist 密钥。需要这些密钥中的一个或两个。如果两个键都不存在,您可以调用 startUpdatingLocation 但位置管理器实际上不会启动。它也不会向委托发送失败消息(因为它从未启动,所以不会失败)。如果您添加一个或两个密钥但忘记明确请求授权,它也会失败。
So the first thing you need to do is to add one or both of the following keys to your Info.plist file:
因此,您需要做的第一件事是将以下一个或两个键添加到您的 Info.plist 文件中:
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Both of these keys take a string which is a description of why you need location services. You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.
这两个键都采用一个字符串,它描述了您为什么需要位置服务。您可以输入类似“Location is required to find your where you are”这样的字符串,就像在 iOS 7 中一样,可以在 InfoPlist.strings 文件中进行本地化。
Next you need to request authorization for the corresponding location method, WhenInUse or Background. Use one of these calls:
接下来需要为相应的定位方法请求授权,WhenInUse 或Background。使用以下调用之一:
[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]
For more information.
欲了解更多信息。
回答by Jesuslg123
I have had the issue that Rashmi Ranjan mallick said in the comments few times since iOS 7 was release. I really think is one bug from iOS 7, they have a tons of them in the new version of iOS.
自 iOS 7 发布以来,我遇到了 Rashmi Ranjan mallick 在评论中多次提到的问题。我真的认为这是 iOS 7 的一个错误,他们在新版本的 iOS 中有很多错误。
For me the issue was the same:
对我来说,问题是一样的:
1.Open the app, never asked about location. iOS was not asking about permissons
2.I went to Settings->Privacy->Location services and my app was not there.
3.I was not able to change the location permissions for my app in any way.
1.打开应用程序,从不询问位置。iOS 没有询问权限
2.我去了设置-> 隐私-> 定位服务,但我的应用程序不在那里。
3.我无法以任何方式更改我的应用程序的位置权限。
One workaround for that is:
一种解决方法是:
1.Kill your app.
2.Disable all location services with the main switch button.
3.Go to your app again.
4.Kill your app.
5.Enable the Location services again on the previous switch button.
6.If still doesn't appear on the list go again to your app, kill it again, and go back to the settings.
7.Now it should be there.
1.杀死你的应用程序。
2.使用主开关按钮禁用所有定位服务。
3.再次转到您的应用程序。
4.杀死你的应用程序。
5.在之前的切换按钮上再次启用定位服务。
6.如果仍然没有出现在列表中,请再次进入您的应用程序,再次将其杀死,然后返回设置。
7.现在它应该在那里。
This worked for me and I hope this is useful.
这对我有用,我希望这是有用的。
UPDATE:if iOS 8be sure you are calling requestWhenInUseAuthorization
or requestAlwaysAuthorization
更新:如果iOS 8确保您正在调用requestWhenInUseAuthorization
或requestAlwaysAuthorization
You may follow this code: :)
你可以按照这个代码::)
#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
回答by Miguel Chaves
Uninstall the app and try running it again.
卸载该应用程序并尝试再次运行它。
If it didn't work, go to the settings and disable the authorization to that app. After that running it again to see if it asks permissions.
如果它不起作用,请转到设置并禁用对该应用程序的授权。之后再次运行它以查看它是否要求权限。
Or:
或者:
You can force the app start monitoring the location with some code like that:
您可以使用以下代码强制应用程序开始监视位置:
self.locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
in your delegate methods you can detect if there an error getting location and you can inform the user.
在您的委托方法中,您可以检测获取位置是否出错,并且可以通知用户。
- (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];
}
If you have any questions tell me.
如果您有任何问题,请告诉我。
回答by Bot
Try adding
尝试添加
[locationManager startUpdatingLocation]
[locationManager startUpdatingLocation]
also make sure that location services is turned on.
还要确保位置服务已打开。
EDIT:
编辑:
Also try deleting the application and re-installing it. There may be a record of that the app is reading which is preventing it from asking for permission to use location.
还可以尝试删除该应用程序并重新安装它。可能有应用程序正在读取的记录阻止它请求使用位置的许可。
回答by Idan
When prompting for location you must not forget those things (iOS 8+):
提示位置时,您一定不要忘记这些事情(iOS 8+):
- Add this flag on your info.plist of the app : NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription depend if you want always access to location or only when app is in usage (the second is recommended if you don't need always access). This is the most important because it is new and weird.
- If you request always permission don't forget to add location updates as background mode on your target capabilities
Make sure you are asking for the right permission when initialise location manager:
-(void)initLocationManager{ locationManager = [[CLLocationManager alloc] init]; locationManager.delegate=self; [locationManager requestAlwaysAuthorization]; // HERE ASK FOR THE RELEVANT }
- 在应用程序的 info.plist 上添加此标志: NSLocationAlwaysUsageDescription 或 NSLocationWhenInUseUsageDescription 取决于您是希望始终访问位置还是仅在应用程序正在使用时(如果您不需要始终访问,建议使用第二个)。这是最重要的,因为它是新的和奇怪的。
- 如果您要求始终获得许可,请不要忘记在目标功能上添加位置更新作为后台模式
确保在初始化位置管理器时请求正确的权限:
-(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.
为了在模拟器中进行测试,我建议您从它的选项中“重置所有内容和设置”。这是获得与应用程序新用户完全相同的体验的唯一方法。