web-dev-qa-db-fra.com

iOS: l'application ne demande pas la permission à l'utilisateur lors de l'installation de l'application. obtenir chaque fois kCLAuthorizationStatusNotDéterminé - Objective-c & Swift

J'essaie de rechercher l'emplacement de l'utilisateur dans mon application iOS. J'ai d'abord inclus le cadre de corelocation dans mon projet. Ensuite, sur un bouton, j'invoque l'api d'emplacement de base comme ci-dessous. Lorsque j'essaie d'installer ceci sur un périphérique, l'emplacement principal ne demande jamais la permission à l'utilisateur. Lorsque j'essaie d'extraire l'emplacement au clic du bouton, j'obtiens kCLAuthorizationStatusNotDetermened comme authorisationStatus. S'il vous plait aidez moi avec ceci. Je n'ai aucune idée de ce qui se passe.

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

C'est ma méthode 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;
}

Voici ma méthode de délégué d'emplacement de base:

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

Je faisais face au même problème. Après avoir réinstallé mon application, elle renvoyait kCLAuthorizationStatusNotDetermined à chaque vérification de [CLLocationManager authorizationStatus] et l'application ne s'est même pas présentée dans Paramètres> Confidentialité> Services de localisation.

La boîte de dialogue d'autorisation invitant iOS à approuver l'accès aux services de localisation est déclenchée sur [locationManager startUpdatingLocation] qui, dans votre cas, n’est jamais appelé (shouldFetchUserLocation sera toujours NO).

La solution de Miguel C. semble être une bonne solution, je vais essayer.

Modifier pour iOS8.x

L’arrivée de iOS8 n’a apporté que peu de changements dans l’utilisation de CLLocationManager. Comme mentionné à plusieurs reprises dans d'autres réponses, il nécessite une étape supplémentaire par rapport à iOS7. Aujourd’hui, j’ai moi-même fait face au problème et j’ai trouvé ceci article (il a été référencé à partir de multiples autres questions mais il complète ma réponse précédente). J'espère que ça aide!

41
David Jirman

iOS8 nous a apporté des modifications majeures de l'API avec le LocationServices

En supposant [CLLocationManager locationServicesEnabled] retourner OUI,

Avec le premier lancement de l’application iOS [iOS7 et iOS8] - locationMangers (CLLocationManager) authorisationStatus prédéfinie sur

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

Invite dans iOS7 +

Lancer le gestionnaire d'emplacement (CLLocationManager, Strong) et définir les délégués (CLLocationManagerDelegate)

Maintenant, inviter l’utilisateur à utiliser les services de localisation et à répertorier l’application sous Paramètres> Confidentialité> Services de localisation, il DOIT appeler l’une des méthodes de services de localisation.

Mises à jour des emplacements - [self.locationManager startUpdatingLocation]

RégionMonitoring - [self.locationManager startMonitoringForRegion:beaconRegion]

immédiatement après l'exécution de la méthode ci-dessus, iOS Invitera l'utilisateur invitant à accepter l'utilisation des services de localisation dans l'application et, quel que soit son choix, l'application sera répertoriée sous Paramètres> Confidentialité> Services de localisation.

Invite dans iOS8 +

C'est dans le même cas avec iOS8, avec le premier lancement des services de localisation d'applications

authorizationStatus(CLAuthorizationStatus) = kCLAuthorizationStatusNotDetermined

iOS 8 nous avons de nouvelles méthodes pour afficher l'invite à l'utilisateur

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

requestAlwaysAuthorization/requestWhenInUseAuthorization disponible sur iOS8. si la cible du déploiement de l'application est iOS7, placez le bloc sous si bloquez pour vous assurer que cela ne provoque pas le blocage de l'application dans iOS7.

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

ou

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

Très important ###:

Conformément à iOS8, il est obligatoire d'inclure la chaîne indiquant pourquoi l'application utilise requestAlwaysAuthorization/requestWhenInUseAuthorization. Dans info.plist, incluez l'une de ces propriétés respectives selon les exigences de l'application.

pour kCLAuthorizationStatusAuthorizedAlways inclut une paire clé/valeur (chaîne de valeur)

NSLocationAlwaysUsageDescription = App use Locations service mode Always

pour kCLAuthorizationStatusAuthorizedWhenInUse, incluez la paire clé/valeur (chaîne de valeur)

NSLocationWhenInUseUsageDescription = App use Locations service mode In Use 

Capture d'écran de info.plist (au cas où quelqu'un serait dérouté par cela) enter image description here

101
Rithesh Rao

Objective-C Suivez les instructions ci-dessous:

iOS-11 Pour iOS 11, jetez un coup d'œil à cette réponse: accès par emplacement pour iOS 11

Besoin d'ajouter deux clés dans la liste et de fournir un message comme ci-dessous:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

enter image description here iOS-10 et inférieur:

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

Méthodes déléguées

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

Code Swift

Suivez les instructions ci-dessous:

iOS-11 Pour iOS 11, jetez un coup d'œil à cette réponse: accès par emplacement pour iOS 11

Besoin d'ajouter deux clés dans la liste et de fournir un message comme ci-dessous:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription

enter image description here iOS-10 et inférieur:

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

Méthodes déléguées

//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

}
29
Alok

Vous devez avoir NSLocationWhenInUseUsageDescription ajouté à votre compte info.plist. C'est un peu bizarre mais il suffit de l'ajouter en tant que valeur de chaîne sans texte, puis, lorsque vous souhaitez localiser, commencez par:

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

[locationManager requestWhenInUseAuthorization];
17
LemonandlIme

Si vous rencontrez ce problème sur iOS8, veuillez utiliser : requestWhenInUseAuthorization.

12
Abhilash Gopal

Dans iOS 8, vous devez effectuer deux opérations supplémentaires pour que votre emplacement fonctionne: ajoutez une clé à votre Info.plist et demandez une autorisation au gestionnaire d’emplacement pour lui demander de démarrer. Il existe deux clés Info.plist pour la nouvelle autorisation d’emplacement. Une ou deux de ces clés est nécessaire. Si aucune des clés n’est présente, vous pouvez appeler startUpdatingLocation mais le gestionnaire de sites ne démarre pas réellement. Il n’enverra pas non plus de message d’échec au délégué (car il n’a jamais commencé, il ne peut pas échouer). Il échouera également si vous ajoutez une ou les deux clés sans oublier de demander explicitement une autorisation.

La première chose à faire est donc d’ajouter une ou les deux clés suivantes à votre fichier Info.plist:

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

Ces deux clés prennent une chaîne décrivant pourquoi vous avez besoin de services de localisation. Vous pouvez entrer une chaîne telle que "L'emplacement est requis pour savoir où vous vous trouvez" qui, comme dans iOS 7, peut être localisée dans le fichier InfoPlist.strings.

Ensuite, vous devez demander une autorisation pour la méthode de localisation correspondante, WhenInUse ou Background. Utilisez l'un de ces appels:

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

Pour plus d'informations .

6
Mohammed Ebrahim

J'ai eu le problème que Rashmi Ranjan Mallick a déclaré dans les commentaires à quelques reprises depuis iOS 7 a été libéré. Je pense vraiment qu’un bogue d’IOS 7 en contient beaucoup dans la nouvelle version d’iOS.

Pour moi, le problème était le même:

1.Ouvrez l'application, jamais demandé sur l'emplacement. iOS ne demandait pas à propos de permissons
2.Je suis allé dans Paramètres-> Confidentialité-> Services de localisation et mon application n'y était pas.
3.Je n'ai pas été en mesure de modifier les autorisations d'emplacement pour mon application.

Une solution de contournement pour cela est:

1. Tuez votre application.
2. Désactivez tous les services de localisation avec le bouton de l'interrupteur principal.
3.Accédez à nouveau à votre application.
4.Kill votre application.
5.Activez à nouveau les services de localisation sur le bouton de commutation précédent.
6.Si la liste n'apparaît toujours pas, retournez dans votre application, tuez-la à nouveau et revenez aux paramètres.
7.Maintenant, il devrait être là.

Cela a fonctionné pour moi et j'espère que cela est utile.

PDATE: si iOS 8 assurez-vous d'appeler requestWhenInUseAuthorization ou requestAlwaysAuthorization

Vous pouvez suivre ce 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
3
Jesuslg123

Désinstallez l'application et essayez de l'exécuter à nouveau.

Si cela ne fonctionne pas, allez dans les paramètres et désactivez l'autorisation pour cette application. Après cela, exécutez-le à nouveau pour voir s'il demande des autorisations.

Ou:

Vous pouvez forcer l'application à surveiller l'emplacement avec un code comme celui-ci:

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

dans vos méthodes de délégation, vous pouvez détecter l’erreur de localisation et informer l’utilisateur.

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

Si vous avez des questions, dites-le moi.

2
Miguel Chaves

Essayez d'ajouter

[locationManager startUpdatingLocation]

assurez-vous également que les services de localisation sont activés.

MODIFIER:

Essayez également de supprimer l'application et de la réinstaller. Il est possible qu'un enregistrement de l'application lise l'empêche de demander la permission d'utiliser l'emplacement.

1
Bot

Lorsque vous demandez l'emplacement, vous ne devez pas oublier ces choses (iOS 8+):

  1. Ajoutez ce drapeau sur votre info.plist de l'application: NSLocationAlwaysUsageDescription ou NSLocationWhenInUseUsageDescription dépendent si vous voulez toujours accéder à l'emplacement ou uniquement lorsque l'application est en cours d'utilisation (la seconde est recommandée si vous n'avez pas besoin d'accéder toujours). C'est le plus important parce que c'est nouveau et bizarre.
  2. Si vous demandez toujours la permission, n'oubliez pas d'ajouter les mises à jour d'emplacement en mode arrière-plan sur les capacités de votre cible.
  3. Assurez-vous de demander la bonne permission lors de l'initialisation du gestionnaire d'emplacement:

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

Pour tester en simulateur, je vous suggère de "Réinitialiser tout le contenu et les paramètres" à partir de ses options. C'est la seule façon d'obtenir exactement la même expérience qu'un nouvel utilisateur de l'application.

1
Idan

J'ai eu un problème similaire, mais causé pour une raison différente. L'ajouter ici au cas où cela pourrait aider quelqu'un d'autre.

J'ai cessé de recevoir le message de demande d'autorisation, et comme il fonctionnait avant que les conditions décrites dans les autres réponses ne soient déjà remplies: clé du plist, vérification du statut de l'autorisation, puis demande de l'autorisation dans iOS 8 +.

Dans mon cas, le problème était lié au mode "Guide d'accès". Ceci est une application pour un kiosque, et il commence seulement à aligner les balises une fois le "Guide d'accès" activé. Mais il semble que les messages de demande d'autorisation ne soient pas envoyés dans ce mode. Je pourrais y remédier simplement en déplaçant la procédure de demande d'autorisation vers le DidLoad de la première vue affichée.

La même chose se produit avec la demande d'utilisation de l'appareil photo.

1
Juan Valera

J'ai rencontré ce problème, mis en œuvre tout ce qui était nécessaire, y compris les clés pList, et mon application ne demandait toujours pas l'emplacement.

Le problème était que la variable locationManager ne pouvait pas être une variable locale, mais bien une variable d'instance.

Donc au lieu de

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

il doit être:

CLLocationManager *locationManager;

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