Les services de localisation ne fonctionnent pas dans iOS 8

608

Mon application qui fonctionnait bien sur iOS 7 ne fonctionne pas avec le SDK iOS 8.

CLLocationManagerne renvoie pas de position, et je ne vois pas non plus mon application dans Paramètres -> Services de localisation . J'ai fait une recherche Google sur le problème, mais rien ne s'est produit. Qu'est-ce qui ne va pas?

özg
la source
Vous pouvez également l'utiliser comme application de référence pour la solution github.com/jbanford/ConstantLocationUpdates
ashok vadivelu
19
J'ai posté quelques-unes des modifications apportées au gestionnaire de localisation dans iOS 8 ici: nevan.net/2014/09/core-location-manager-changes-in-ios-8
nevan king
2
Vous pouvez essayer d'utiliser cette bibliothèque qui simplifie les API Core Location et expose une belle interface basée sur les blocs, et normalise toutes les différences entre les différentes versions d'iOS (divulgation complète: je suis l'auteur): github.com/lmirosevic/GBLocation
lms
J'ai trouvé une référence ici datacalculation.blogspot.in/2014/11/…
Test iOS
2
@nevanking Vous monsieur! besoin d'une couronne! Je me bats avec ce problème depuis le changement et je n'ai pas encore trouvé de "guide" pour le résoudre, qui était amical noob .. Votre guide a fait un idiot comme moi, gérer le problème moi-même. Merci beaucoup pour ce lien.
Patrick R

Réponses:

1086

J'ai fini par résoudre mon propre problème.

Apparemment, dans le SDK iOS 8, requestAlwaysAuthorization(pour l'emplacement en arrière-plan) ou requestWhenInUseAuthorization(emplacement uniquement au premier plan), un appel CLLocationManagerest nécessaire avant de commencer les mises à jour de l'emplacement.

Il faut aussi être NSLocationAlwaysUsageDescriptionou NSLocationWhenInUseUsageDescriptionclé dans Info.plistun message à afficher dans l'invite. L'ajout de ceux-ci a résolu mon problème.

entrez la description de l'image ici

J'espère que cela aide quelqu'un d'autre.

EDIT: Pour plus d'informations, consultez: Core-Location-Manager-Changes-in-ios-8

özg
la source
6
pouvez-vous partager la valeur exacte mise à jour dans Info.plist? Je ne peux pas voir cette clé dans mon Info.plist. Je l'ai ajouté et cela ne semble toujours pas fonctionner. J'utilise Swift, iOS8 et XCode 6 beta 4
Vijay Kumar AB
4
@Vjay - vous devez éditer le fichier Info.plist dans un éditeur, vous ne pouvez pas définir ces clés dans Xcode (à partir de la bêta 6).
Kendall Helmstetter Gelner
11
Juste un rappel, si vous ne voulez pas montrer d'explication personnalisée à l'utilisateur, définissez simplement cette clé sur une chaîne vide.
2014
7
Vous devez conserver votre locationManager pour le faire fonctionner. alors faites de votre CLLocationManager une propriété solide
Vassily
273
J'AIME que vous n'obtenez aucune erreur, aucun avertissement, aucun message de journal, RIEN si vous omettez l'entrée plist. Fondamentalement, Apple a créé un appel d'API qui ne fait RIEN si vous ne disposez pas de l'entrée plist appropriée. Merci à @OrtwinGentz ​​d'avoir compris cela.
MobileVet
314

J'arrachais mes cheveux avec le même problème. Xcode vous donne l'erreur:

Essayer de démarrer MapKitles mises à jour de localisation sans demander l'autorisation de localisation. Doit appeler -[CLLocationManager requestWhenInUseAuthorization]ou d' -[CLLocationManager requestAlwaysAuthorization]abord.

Mais même si vous implémentez l'une des méthodes ci-dessus, cela n'invitera pas l'utilisateur sauf s'il existe une entrée dans info.plist pour NSLocationAlwaysUsageDescriptionou NSLocationWhenInUseUsageDescription.

Ajoutez les lignes suivantes à votre info.plist où les valeurs de chaîne représentent la raison pour laquelle vous avez besoin d'accéder à l'emplacement des utilisateurs

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

Je pense que ces entrées peuvent avoir été manquantes depuis que j'ai commencé ce projet dans Xcode 5. Je suppose que Xcode 6 pourrait ajouter des entrées par défaut pour ces clés, mais elles n'ont pas été confirmées.

Vous pouvez trouver plus d'informations sur ces deux paramètres ici

Henri
la source
13
xcode 6 n'ajoute pas ces clés par défaut, si vous avez l'intention d'implémenter CLLocationManager, vous devez les ajouter manuellement
Wesley Smith
1
J'ai également dû les ajouter manuellement, je n'ai pas pu les ajouter via la vue RawValues ​​de info.plist dans Xcode6!
Kendall Helmstetter Gelner
1
j'ai toujours cherché ça. Mon message [CLLLocationManager authorizationStatus] ne renvoyait qu'une valeur <nil>. Après avoir ajouté les clés ci-dessus, il a commencé à renvoyer les énumérations respectives pour la sortie des messages. D'après ce que j'ai trouvé, c'est un bug connu d'iOS 8, mais je n'ai rien trouvé dans mon contexte pendant des siècles. Merci un mil!
MrOli3000
4
J'aime la valeur de la chaîne que vous mettez
Chris Chen
1
Le message apparaîtra comme sous-message dans l'alerte qui demande si l'utilisateur souhaite partager sa position. En tant que tel, le simple fait d'être vide (vide) semble avoir le plus de sens dans mon application. Une explication de la raison pour laquelle vous souhaitez utiliser la localisation aurait également un sens. Cependant, NSLocationWhenInUseUsageDescription ne s'est pas comporté comme prévu pour moi (c.-à-d. A continué d'obtenir une autorisation refusée, même si la valeur de retour était correcte). NSLocationAlwaysUsageDescription a bien fonctionné.
arcady bob
104

Pour vous assurer que cela est rétrocompatible avec iOS 7, vous devez vérifier si l'utilisateur exécute iOS 8 ou iOS 7. Par exemple:

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
   [self.locationManager requestAlwaysAuthorization];
}

[self.locationManager startUpdatingLocation];
JKoko
la source
164
Une meilleure façon que de vérifier la version est de vérifier si l'objet a ce sélecteur, par exemple: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
progrmr
1
J'ai eu du mal à simplement implémenter la solution de @ progrmr lors de la construction sur Xcode 5, car il ne sait pas quelle est la requestAlwaysAuthorizationméthode. Ma solution supplémentaire était d'utiliser cette ligne dans la ifdéclaration au lieu d'un appel de méthode normale: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. C'est peut-être évident pour d'autres personnes, mais il m'a fallu un certain temps pour comprendre. Je pense que c'est la bonne solution jusqu'à la sortie du Xcode 6 final.
VinceFior
2
La bonne solution est de construire avec Xcode 6. Si vous construisez avec Xcode 5, vous n'avez pas besoin de demander d'autorisation, c'est automatique.
progrmr
Vous pourriez avoir un point. Ma préoccupation était que je voulais que mon code soit compilé dans Xcode 5 (même s'il ne fonctionnera pas sur iOS 8 à moins d'être compilé dans Xcode 6) pendant que mon équipe passe à Xcode 6. Mais c'est peut-être un meilleur flux de travail pour écrire le code normalement et pas le fusionner jusqu'à ce que nous passions à Xcode 6 .. Merci.
VinceFior
@VinceFior l'approche recommandée est de compiler conditionnellement en utilisant la macro définie par le SDK __IPHONE_OS_VERSION_MAX_ALLOWED( #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
Steven Kramer
50
- (void)startLocationManager
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
    [locationManager requestWhenInUseAuthorization]; // Add This Line


}

Et dans votre fichier info.plist entrez la description de l'image ici

neo D1
la source
1
Trouvé une solution similaire de manière plus descriptive sur datacalculation.blogspot.in/2014/11/…
Test iOS
2
@Hemang: selon la documentation Apple Dev: il est sûr de démarrer les services de localisation avant que le statut d'autorisation de votre application ne soit déterminé. Bien que vous puissiez démarrer les services de localisation, ces services ne livrent aucune donnée tant que l'état de l'autorisation ne passe pas à kCLAuthorizationStatusAuthorizedAlways ou kCLAuthorizationStatusAuthorizedWhenInUse.
Andrew
Un peu en retard, mais je vous recommande de cacher les parties non pertinentes de votre fichier plist, en particulier FacebookAppID
Przemysław Wrzesiński
Merci mais c'est juste un échantillon fictif :)
neo D1
Il est également important que le projet pointe vers le bon info.plist (celui où la clé est définie). Cela est déterminé dans les paramètres de construction du projet sous Fichier Info.plist.
clearlight
30

Selon les documents Apple:

Depuis iOS 8, la présence d'une NSLocationWhenInUseUsageDescriptionou d'une NSLocationAlwaysUsageDescriptionvaleur clé dans le fichier Info.plist de votre application est requise. Il est donc également nécessaire de demander l' autorisation de l'utilisateur de l' enregistrement avant pour les mises à jour de localisation, soit en appelant [self.myLocationManager requestWhenInUseAuthorization]ou en [self.myLocationManager requestAlwaysAuthorization]fonction de vos besoins. La chaîne que vous avez entrée dans Info.plist sera alors affichée dans la boîte de dialogue suivante.

Si l'utilisateur accorde la permission, c'est comme d'habitude. S'ils refusent l'autorisation, le délégué n'est pas informé des mises à jour de l'emplacement.

métathéorétique
la source
J'ai trouvé une description simple ici à datacalculation.blogspot.in/2014/11/…
Test iOS
28
- (void)viewDidLoad
{

    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
        NSUInteger code = [CLLocationManager authorizationStatus];
        if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
            // choose one request according to your business.
            if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
                [self.locationManager requestAlwaysAuthorization];
            } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
                [self.locationManager  requestWhenInUseAuthorization];
            } else {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
            }
        }
    }
    [self.locationManager startUpdatingLocation];
}

>  #pragma mark - CLLocationManagerDelegate

    - (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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"didUpdateToLocation: %@", newLocation);
        CLLocation *currentLocation = newLocation;

        if (currentLocation != nil) {
            longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
            latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
        }
    }

Dans iOS 8, vous devez faire deux choses supplémentaires pour que la localisation fonctionne: Ajoutez une clé à votre Info.plist et demandez l'autorisation au gestionnaire de localisation lui demandant de démarrer. Il existe deux clés Info.plist pour la nouvelle autorisation de localisation. Une ou ces deux clés sont requises. Si aucune des clés n'est là, vous pouvez appeler startUpdatingLocation mais le gestionnaire d'emplacement ne démarre pas réellement. Il n'enverra pas non plus de message d'échec au délégué (puisqu'il n'a jamais démarré, il ne peut pas échouer). Il échouera également si vous ajoutez une ou les deux clés mais oubliez de demander explicitement l'autorisation. Par conséquent, la première chose que vous devez faire est d'ajouter une ou les deux clés suivantes à votre fichier Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Ces deux clés prennent une chaîne

qui explique pourquoi vous avez besoin de services de localisation. Vous pouvez entrer une chaîne comme «L'emplacement est requis pour savoir où vous êtes» qui, comme dans iOS 7, peut être localisé dans le fichier InfoPlist.strings.

entrez la description de l'image ici

Adarsh ​​GJ
la source
19

Ma solution qui peut être compilée dans Xcode 5:

#ifdef __IPHONE_8_0
    NSUInteger code = [CLLocationManager authorizationStatus];
    if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
        // choose one request according to your business.
        if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
            [self.locationManager requestAlwaysAuthorization];
        } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
            [self.locationManager  requestWhenInUseAuthorization];
        } else {
            NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
        }
    }
#endif
    [self.locationManager startUpdatingLocation];
Yinfeng
la source
2
Belle solution dynamique, à utiliser dans toutes les applications. Je changerais cependant la commande et au lieu de vérifier pour l'iphone 8.0, je vérifierais si le gestionnaire d'emplacement répond à l'autorisation, puis j'exécute l'autorisation pour obtenir le code. Cela le rendra plus universel.
zirinisp
A également fonctionné sur xCode 7.2.
Totoro
17

L'ancien code pour demander l'emplacement ne fonctionnera pas dans iOS 8. Vous pouvez essayer cette méthode pour l'autorisation d'emplacement:

- (void)requestAlwaysAuthorization
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    // If the status is denied or only granted for when in use, display an alert
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status ==        kCLAuthorizationStatusDenied) {
        NSString *title;
        title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" :   @"Background location is not enabled";
        NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];
        [alertView show];
    }
    // The user has not enabled any location services. Request background authorization.
    else if (status == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // Send the user to the Settings for this app
        NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:settingsURL];
    }
}
Nits007ak
la source
UIAlertView est obsolète. Vous devez plutôt utiliser UIAlertController.
Pasan Premaratne
ouais je sais que c'est obsolète mais ça marchera aussi. mais oui, il vaut mieux utiliser UIAlertController pour IOS8.
Nits007ak
12

Dans iOS 8, vous devez faire deux choses supplémentaires pour que la localisation fonctionne: Ajoutez une clé à votre Info.plist et demandez l'autorisation au gestionnaire de localisation lui demandant de démarrer

info.plist:

<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>

Ajoutez ceci à votre code

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}
parJeevan
la source
1
il n'est pas clair si votre pseudocode est un appel de préprocesseur ou un appel régulier
El Dude
1
Ajoutez ceci à votre fichier constants.h ou .pch: #define IS_OS_8_OR_LATER ([[UIDevice currentDevice] .systemVersion floatValue]> = 8.0)
OxenBoxen
Pourquoi voudriez-vous demander les deux, vous devez ajouter un commentaire mentionnant uniquement l'utilisation de l'un ou l'autre en fonction des besoins de votre application
powerj1984
la partie info.plist est assez facile à faire dans Unity3d, mais comment ajouter la partie code si vous utilisez unity3d? où ?
CthulhuJon
11

Une erreur courante pour les développeurs Swift:

Assurez-vous d'abord d'ajouter une valeur à la liste pour soit NSLocationWhenInUseUsageDescriptionou NSLocationAlwaysUsageDescription.

Si vous ne voyez toujours pas de fenêtre vous demander l'autorisation, vérifiez si vous mettez la ligne var locationManager = CLLocationManager()dans la viewDidLoadméthode de votre contrôleur de vue . Si vous le faites, même si vous appelez locationManager.requestWhenInUseAuthorization(), rien n'apparaîtra . En effet, après l'exécution de viewDidLoad, la variable locationManager est désallouée (effacée).

La solution consiste à localiser la ligne var locationManager = CLLocationManager()en haut de la méthode de classe.

st.derrick
la source
9

Avant [locationManager startUpdatingLocation];, ajoutez une demande de services de localisation iOS8:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Modifiez votre application Info.plistet ajoutez une clé NSLocationAlwaysUsageDescriptionavec la valeur de chaîne qui sera affichée pour l'utilisateur (par exemple, We do our best to preserve your battery life.)

Si votre application n'a besoin de services de localisation que lorsqu'elle est ouverte, remplacez:

requestAlwaysAuthorizationavec requestWhenInUseAuthorizationet

NSLocationAlwaysUsageDescriptionavec NSLocationWhenInUseUsageDescription.

budidino
la source
9

Je travaillais sur une application mise à niveau vers iOS 8 et les services de localisation ont cessé de fonctionner. Vous obtiendrez probablement une erreur dans la zone de débogage comme ceci:

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

J'ai fait la procédure la moins intrusive. Ajoutez d'abord une NSLocationAlwaysUsageDescriptionentrée à votre info.plist:

Entrez la description de l'image ici

Notez que je n'ai pas rempli la valeur de cette clé. Cela fonctionne toujours, et je ne suis pas inquiet car il s'agit d'une application interne. De plus, il existe déjà un titre demandant à utiliser les services de localisation, donc je ne voulais rien faire de redondant.

Ensuite, j'ai créé un conditionnel pour iOS 8:

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

Après cela, la locationManager:didChangeAuthorizationStatus:méthode est appelée:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}

Et maintenant, tout fonctionne bien. Comme toujours, consultez la documentation .

Kris Utter
la source
7

Solution avec compatibilité descendante:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Configurez la clé NSLocationWhenInUseUsageDescription dans votre Info.plist

hrchen
la source
2
Ce n'est pas correct, qu'en est-il du cas kCLAuthorizationStatusDenied? il passe à autre chose et commence à mettre à jour l'emplacement qui n'est pas correct!
electronix384128
@BenMarten Je ne pense pas que cela devrait avoir d'importance. Vous devriez gérer cela vous-même locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. Il a cependant oublié d'ajouter startUpdatingLocation à l'instruction if donc après l'avoir acceptée ou refusée, elle n'appelle pas réellement startUpdateLocation.
Chris
6

Solution avec compatibilité descendante qui ne génère pas d'avertissements Xcode:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
  [self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
  [self.locationManager startUpdatingLocation];
} else {
  [self.locationManager startUpdatingLocation];
}

NSLocationWhenInUseUsageDescriptionClé de configuration dans votre Info.plist.

Pour iOS version 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionclé d' installation dans votre Info.plist. avec 2 autres clés.

Alexander Belyavskiy
la source
Ce n'est pas correct, qu'en est-il du cas kCLAuthorizationStatusDenied? il passe à autre chose et commence à mettre à jour l'emplacement qui n'est pas correct!
electronix384128
C'est assez étrange, cela fonctionne bien pour moi pas très bien avec les deux permettre et ne pas permettre.Même la solution Jacob semble précise mais n'a pas fonctionné pour moi. Étrange mais travaillé !!!
josh
Appeler [self.locationManager startUpdatingLocation] juste après requestWhenInUseAuthorization n'a aucun intérêt
Kostia Kim
5

C'est un problème avec iOS 8 Ajoutez ceci à votre code

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

et à info.plist:

 <key>NSLocationUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationAlwaysUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>I need location</string>
Pooja Patel
la source
NSLocationUsageDescriptionn'est pas utilisé sur iOS8 +
Carlos Ricardo
4

Pour accéder à l'emplacement utilisateur dans iOS 8, vous devrez ajouter,

NSLocationAlwaysUsageDescription in the Info.plist 

Cela demandera à l'utilisateur l'autorisation d'obtenir son emplacement actuel.

Annu
la source
4

Procédure Objective-C Suivez les instructions ci-dessous:

Pour iOS-11 Pour iOS 11 jetez un œil à cette réponse: accès à l'emplacement iOS 11

Besoin d'ajouter deux clés dans plist et de fournir un message comme l'image ci-dessous:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

entrez la description de l'image ici Pour iOS-10 et inférieur:

NSLocationWhenInUseUsageDescription

entrez la description de l'image ici

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
    [locationManager requestWhenInUseAuthorization];
}else{
    [locationManager startUpdatingLocation];
} 

Déléguer les méthodes

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

Procédure rapide

Suivez les instructions ci-dessous:

Pour iOS-11 Pour iOS 11 jetez un œil à cette réponse:accès à l'emplacement iOS 11

Besoin d'ajouter deux clés dans plist et de fournir un message comme l'image ci-dessous:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

entrez la description de l'image ici Pour iOS-10 et inférieur:

entrez la description de l'image ici

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

Déléguer les méthodes

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

}
Alok
la source
Veuillez vous assurer que NSLocationAlwaysUsageDescription est également ajouté, sinon vous obtiendrez une erreur lors du téléchargement sur l'App Store.
Alok
Votre message doit également être informatif, sinon Apple rejettera l'application pendant le processus de révision.
Alok
3

Pour ceux qui utilisent Xamarin , j'ai dû ajouter la clé NSLocationWhenInUseUsageDescriptionà info.plist manuellement car elle n'était pas disponible dans les listes déroulantes de Xamarin 5.5.3 Build 6 ou XCode 6.1 - seule NSLocationUsageDescriptionfigurait dans la liste, ce qui a provoqué la CLLocationManagerpoursuite de la échouent silencieusement.

Derreck Dean
la source
2
        // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string

        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
        if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [self.locationManager requestWhenInUseAuthorization];
        }
        [self.locationManager startUpdatingLocation];


    // Location Manager Delegate Methods    
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        NSLog(@"%@", [locations lastObject]);

}
Prosenjit Goswami
la source
2

Un petit assistant pour vous tous qui avez plus d'un fichier Info.plist ...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

Il ajoutera la balise nécessaire à tous les fichiers Info.plist du répertoire actuel (et des sous-dossiers).

Un autre est:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

Il ajoutera votre description à tous les fichiers.

Peter Mortensen
la source
2

J'obtiens une erreur similaire dans iOS9 (en travaillant avec Xcode 7 et Swift 2): j'essaie de démarrer les mises à jour de localisation de MapKit sans demander l'autorisation de localisation. Doit appeler - [CLLocationManager requestWhenInUseAuthorization] ou - [CLLocationManager requestAlwaysAuthorization] en premier. Je suivais un tutoriel mais le tuteur utilisait iOS8 et Swift 1.2. Il y a quelques changements dans Xcode 7 et Swift 2, j'ai trouvé ce code et cela fonctionne bien pour moi (si quelqu'un a besoin d'aide):

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // MARK: Properties
    @IBOutlet weak var mapView: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.mapView.showsUserLocation = true

    }

    // MARK: - Location Delegate Methods

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
        self.mapView.setRegion(region, animated: true)
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Errors: " + error.localizedDescription)
    }
}

Enfin, je mets cela dans info.plist: Liste des propriétés d'informations: NSLocationWhenInUseUsageDescription Valeur: l' application a besoin de serveurs de localisation pour le personnel

Jorge Luis Jiménez
la source
2

Afin d'accéder à l'emplacement des utilisateurs dans iOS. Vous devez ajouter deux clés

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

dans le fichier Info.plist.

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Because I want to know where you are!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Want to know where you are!</string>

Voir cette image ci-dessous.

Image Info.plist

Vinoth Vino
la source
1
  1. Ajouter une clé NSLocationWhenInUseUsageDescriptionou NSLocationAlwaysUsageDescription(utilisation du GPS en arrière-plan) avec une chaîne demandant d'utiliser le GPS sur chacun info.plistde chaque cible.

  2. Demandez la permission en exécutant:

    [self initLocationManager: locationManager];

initLocationManagerest:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

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

N'oubliez pas que si les clés ne sont pas sur chacune info.plistpour chaque cible, l'application ne demandera pas à l'utilisateur. Le iffournit la compatibilité avec iOS 7 et la respondsToSelector:méthode garantit la compatibilité future plutôt que de simplement résoudre le problème pour iOS 7 et 8.

juan Isaza
la source
0

Le problème pour moi était que la classe qui était CLLocationManagerDelegateétait privée, ce qui empêchait toutes les méthodes déléguées d'être appelées. Je suppose que ce n'est pas une situation très courante, mais j'ai pensé que je le mentionnerais au cas où cela aiderait quelqu'un.

Lorenzo
la source
0

Ajouter ceux clé dans InfoPlist.stringsdans iOS 8.4, mini iPad 2. Il fonctionne aussi. Je ne mets aucune clé, comme NSLocationWhenInUseUsageDescription, dans mon Info.plist.


InfoPlist.strings :

"NSLocationWhenInUseUsageDescription" = "I need GPS information....";

La base de ce fil , dit-il as in iOS 7, peut être localisée dans InfoPlist.strings. Dans mon test, ces clés peuvent être configurées directement dans le fichier InfoPlist.strings.

Donc, la première chose que vous devez faire est d'ajouter une ou les deux clés suivantes à votre fichier Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

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


MISE À JOUR:

Je pense que @IOSla méthode est meilleure. Ajoutez la clé à Info.plistavec une valeur vide et ajoutez des chaînes localisées à InfoPlist.strings.

AechoLiu
la source