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

Я пытаюсь найти местоположение пользователя в приложении iOS. Вначале я включил рамки коллиляции. Затем при нажатии кнопки я вызываю базовое расположение 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];
    }
}

Это мой метод toFetchUserLocation:

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

Ответ 1

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

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

Решение Miguel C. кажется хорошим решением, попробуем это.

Изменить для iOS8.x

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

Ответ 2

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

Если предположить, [CLLocationManager locationServicesEnabled] return YES,

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

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

Запрос в iOS7 +

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

Теперь, чтобы предложить пользователю использовать службы локаций и отобразить приложение в разделе "Настройки" > "Конфиденциальность" > "Службы местоположений", ДОЛЖНО позвонить любому из методов служб местоположений, его зависит от требования приложения - например, если приложение является одним из ниже

Обновления местоположений - [self.locationManager startUpdatingLocation]

RegionMonitoring - [self.locationManager startMonitoringForRegion:beaconRegion]

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

Запрос в iOS8 +

В том же случае с iOS8, при первом запуске Службы App Locations Services

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 его обязательное включение строки, указывающей, почему приложение использует requestAlwaysAuthorization/requestWhenInUseAuthorization В info.plist включено любое из этих свойств, соответствующее требованию приложения

для kCLAuthorizationStatusAuthorizedAlways включает пару Key/Value (string value)

NSLocationAlwaysUsageDescription = App use Locations service mode Always

для kCLAuthorizationStatusAuthorizedWhenInUse включает в себя пару Key/Value (string value)

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use 

Снимок экрана с сайта info.plist(в случае, если кто-то путается этим) введите описание изображения здесь

Ответ 3

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

КСН-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 Code

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

КСН-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

}

Ответ 4

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

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

[locationManager requestWhenInUseAuthorization];

Ответ 5

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

Ответ 6

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

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

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

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

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

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

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

Ответ 7

У меня была проблема, что Rashmi Ranjan mallick сказал в комментариях несколько раз с момента выхода iOS 7. Я действительно думаю, что это одна ошибка от iOS 7, у них их много в новой версии iOS.

Для меня вопрос был одинаков:

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

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

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

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

UPDATE:, если 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

Ответ 8

Удалите приложение и попробуйте запустить его снова.

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

Или:

Вы можете заставить приложение запускать мониторинг местоположения с помощью некоторого кода:

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

Если у вас есть вопросы, расскажите мне.

Ответ 9

Попробуйте добавить

[locationManager startUpdatingLocation]

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

EDIT:

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

Ответ 10

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

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

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

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

Ответ 11

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

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

Итак, вместо

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

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

CLLocationManager *locationManager;

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

Ответ 12

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

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

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

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