iOS: приложение не запрашивает разрешения пользователя при установке приложения. получение kCLAuthorizationStatusNotDetermined каждый раз-цель-c & Swift

Я пытаюсь получить местоположение пользователя в моем приложении iOS. Сначала я включил CoreLocation framework в свой проект. Затем нажмите кнопку, и я вызову Core location api, как показано ниже. Когда я пытаюсь установить это в устройстве, ядро никогда не запрашивает разрешение пользователя. Когда я пытаюсь получить местоположение при нажатии кнопки, я получаю 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 %+.6fn",
              location.coordinate.latitude,
              location.coordinate.longitude);
    }
    NSLog(@"latitude %+.6f, longitude %+.6fn",
          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;
    }
}

12 ответов


я столкнулся с той же проблемой, после повторной установки моего приложения он возвращался kCLAuthorizationStatusNotDetermined при проверке [CLLocationManager authorizationStatus] и приложение даже не появилось в настройках > Конфиденциальность > Службы определения местоположения.

диалог авторизации, который iOS предлагает пользователю утвердить доступ к службам определения местоположения, запускается на [locationManager startUpdatingLocation] который в вашем случае никогда не называется (shouldFetchUserLocation будет всегда NO).

решение Мигеля К. кажется хорошим решением, попробует что.

редактировать для iOS8.x

когда iOS8 пришел, он принес мало изменений в способе использования CLLocationManager. Как упоминалось несколько раз в других ответах, это требует дополнительного шага по сравнению с iOS7. Сегодня я сам столкнулся с проблемой и нашел это статьи (на него ссылались из нескольких других вопросов, но он завершает мой предыдущий ответ). Надеюсь, это поможет!


iOS8 получил нас основные изменения API с LocationsServices

предполагая [CLLocationManager locationServicesEnabled] вернуться да

при первом запуске приложения iOS [как iOS7, так и iOS8] - locationMangers (CLLocationManager) authorizationStatus настроек к

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

Подсказка в iOS7+

инициировать locationManger (CLLocationManager , Сильный) и установить делегатов (CLLocationManagerDelegate)

теперь, чтобы предложить пользователю использовать Locations Services и перечислите приложение в разделе Настройки> Конфиденциальность> Locations Services его необходимо вызвать любой из методов Locations Services, его зависит от требования приложения - например, если приложение является одним из ниже

Изменения Локаций - [self.locationManager startUpdatingLocation]

RegionMonitoring -[self.locationManager startMonitoringForRegion:beaconRegion]

сразу после выполнения вышеуказанного метода iOS предложит пользователю принять использование сервисов местоположений в приложении и независимо от выбора пользователя приложение будет перечислены в разделе Параметры > Конфиденциальность > расположение услуги.

Подсказка в iOS8+

его в том же случае с iOS8, с первым запуском приложения Locations Services

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

iOS 8 мы получили новые методы для отображения подсказки пользователю

[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 В информации.plist включают любой из этих свойств, соответствующих требованию приложения

для kclauthorizationstatusauthorizedalways включают пару ключ/значение(строковое значение)

NSLocationAlwaysUsageDescription = App use Locations service mode Always

для kclauthorizationstatusauthorizedwheninuse включает пару ключ/значение(строковое значение)

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use 

скриншот информация.plist (в случае, если кто-то смущен этим) enter image description here


С Следуйте приведенным ниже инструкциям:

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

}

вы должны NSLocationWhenInUseUsageDescription добавлено к вам info.plist. Это немного странно, но просто добавьте его как строковое значение без текста, а затем, когда вы хотите начать с:

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

[locationManager requestWhenInUseAuthorization];

Если вы столкнулись с этой проблемой на iOS8, пожалуйста, используйте : requestWhenInUseAuthorization.


в iOS 8 вам нужно сделать две дополнительные вещи, чтобы сделать место работы: добавить ключ к вашей информации.plist и запросить авторизацию у менеджера местоположения с просьбой запустить его. Есть две информации.ключи plist для авторизации нового местоположения. Требуется один или оба ключа. Если ни один из ключей не существует, вы можете вызвать startUpdatingLocation, но менеджер местоположений фактически не запустится. Он также не отправит сообщение об ошибке делегату (поскольку он никогда не запускался, он не может потерпеть неудачу). Он также произойдет сбой, если вы добавите один или оба ключа, но забудете явно запросить авторизацию.

Итак, первое, что вам нужно сделать, это добавить одно или оба из следующих ключей к вашей информации.plist file:

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

оба этих ключа принимают строку, которая является описанием того, почему вам нужны службы определения местоположения. Вы можете ввести строку типа "местоположение требуется, чтобы узнать, где вы находитесь", которая, как и в iOS 7, может быть локализована в InfoPlist.веревка файл.

Далее нужно запросить авторизацию для данного метода, WhenInUse или фон. Используйте один из следующих вызовов:

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

на дополнительная информация.


у меня была проблема, которую Рашми Ранджан Маллик сказал в комментариях несколько раз, так как iOS 7 был выпущен. Я действительно думаю, что одна ошибка с iOS 7, у них есть тонны их в новой версии iOS.

для меня вопрос был тот же:

1.Откройте приложение, никогда не спрашивали о местоположении. iOS не спрашивал о разрешениях
2.Я пошел в Настройки- > Конфиденциальность - >Службы определения местоположения, и моего приложения там не было.
3.Я не смог изменить разрешения место для мое приложение в любом случае.

один обходной путь для этого:

1.Убейте приложение.
2.Отключите все службы определения местоположения с помощью кнопки main switch.
3.Снова зайдите в приложение.
4.Убейте приложение.
5.Включите службы определения местоположения снова на предыдущей кнопке переключателя.
6.Если все еще не отображается в списке, снова перейдите в приложение, снова убейте его и вернитесь к настройкам.
7.Теперь он должен быть там.

этот работал на меня, и я надеюсь, что это полезно.

обновление: если iOS 8 убедитесь, что вы звоните requestWhenInUseAuthorization или requestAlwaysAuthorization

вы можете следовать этому коду::)

#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]

также убедитесь, что службы определения местоположения включены.

изменить:

также попробуйте удалить приложение и переустановить его. Может быть запись о том, что приложение читает, что мешает ему запрашивать разрешение на использование местоположения.


при запросе местоположения вы не должны забывать эти вещи (iOS 8+):

  1. добавьте этот флаг в свою информацию.plist приложения: NSLocationAlwaysUsageDescription или NSLocationWhenInUseUsageDescription зависят, хотите ли вы всегда иметь доступ к местоположению или только когда приложение используется (второй рекомендуется, если вам не нужен всегда доступ). Это самое важное, потому что это ново и странно.
  2. если вы запрашиваете всегда разрешение, не забудьте добавить обновления местоположения в фоновом режиме на ваших целевых возможностей
  3. убедитесь, что вы запрашиваете правильное разрешение при инициализации диспетчера местоположения:

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

для тестирования в симуляторе я предлагаю вам "сбросить контент и настройки" из вариантов. Это единственный способ получить тот же самый опыт, который получит новый пользователь приложения.


я столкнулся с этой проблемой, реализовал все необходимые вещи, включая ключи pList, и мое приложение все еще не запрашивало местоположение.

оказывается, проблема заключалась в том, что переменная locationManager не может быть локальной - она должна быть переменной экземпляра.

Так вместо

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

это должно быть:

CLLocationManager *locationManager;

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

У меня была аналогичная проблема, но по другой причине. Добавим его сюда на случай, если это поможет кому-то еще.

Я перестал получать сообщение с запросом авторизации, и поскольку он работал до того, как были выполнены требования, описанные в других ответах: ключ в plist, проверка статуса авторизации, а затем запрос разрешения в ios8+.

в моем случае проблема была связана с режимом "руководство по доступу". Это приложение для киоска, и это только начинает диапазон маяков, как только активируется "руководство доступа". Но похоже, что сообщения запроса авторизации не отправляются в этом режиме. Я мог бы исправить это, просто переместив процедуру авторизации запроса на загрузку первого отображаемого представления.

то же самое происходит с запросом на использование камеры.