Services de localisation ne fonctionnant pas dans iOS 8

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

CLLocationManager ne CLLocationManager pas d’emplacement et je ne vois pas non plus mon application sous Paramètres -> Services de localisation . J’ai fait une recherche sur Google à ce sujet, mais rien n’a été fait. Qu’est-ce qui pourrait être faux?

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

Apparemment, dans iOS 8 SDK, l’ requestAlwaysAuthorization (pour l’emplacement d’arrière-plan) ou de requestWhenInUseAuthorization (emplacement uniquement lorsque l’avant-plan) sur CLLocationManager est nécessaire avant de commencer les mises à jour d’emplacement.

Il doit également y avoir NSLocationAlwaysUsageDescription clé NSLocationAlwaysUsageDescription ou NSLocationWhenInUseUsageDescription dans Info.plist avec un message à afficher dans l’invite. L’ajout de ceux-ci a résolu mon problème.

entrer la description de l'image ici

J’espère que ça aide quelqu’un d’autre.

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

Je tirais mes cheveux avec le même problème. Xcode vous donne l’erreur:

Essayer de démarrer les mises à jour d’emplacement MapKit sans demander l’autorisation d’emplacement. Doit appeler -[CLLocationManager requestWhenInUseAuthorization] ou -[CLLocationManager requestAlwaysAuthorization] premier.

Mais même si vous implémentez l’une des méthodes ci-dessus, elle n’invite pas l’utilisateur, sauf s’il existe une entrée dans info.plist pour NSLocationAlwaysUsageDescription ou 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 de l’utilisateur

 NSLocationWhenInUseUsageDescription This application requires location services to work NSLocationAlwaysUsageDescription This application requires location services to work 

Je pense que ces entrées ont peut-être été manquantes depuis que j’ai démarré ce projet dans Xcode 5. Je suppose que Xcode 6 pourrait append des entrées par défaut pour ces clés mais qu’elles ne sont pas confirmées.

Vous pouvez trouver plus d’informations sur ces deux parameters ici

Pour vous assurer qu’il est rétro-compatible avec iOS 7, vous devez vérifier si l’utilisateur utilise 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]; 
 - (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 à votre fichier info.plist entrer la description de l'image ici

Selon les documents Apple:

À partir d’iOS 8, la présence d’une NSLocationWhenInUseUsageDescription ou NSLocationAlwaysUsageDescription dans le fichier Info.plist de votre application est requirejse. Il est également nécessaire de demander l’autorisation à l’utilisateur avant de s’inscrire aux mises à jour d’emplacement, en appelant [self.myLocationManager requestWhenInUseAuthorization] ou [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 dialog 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.

 - (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 = [NSSsortingng ssortingngWithFormat:@"%.8f", currentLocation.coordinate.longitude]; latitudeLabel.text = [NSSsortingng ssortingngWithFormat:@"%.8f", currentLocation.coordinate.latitude]; } } 

Dans iOS 8, vous devez faire deux choses supplémentaires pour que votre localisation fonctionne: Ajoutez une clé à votre Info.plist et demandez l’autorisation au gestionnaire de localisation pour lui demander de démarrer. Il existe deux clés Info.plist pour la nouvelle autorisation de localisation. L’une ou l’autre de ces clés est requirejse. Si aucune des clés n’est présente, vous pouvez appeler startUpdatingLocation mais le gestionnaire de localisation ne démarrera pas réellement. Il n’enverra pas non plus un 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 une autorisation. Donc, la première chose à faire est d’append une ou les deux clés suivantes à votre fichier Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Ces deux clés prennent une chaîne

ce qui explique pourquoi vous avez besoin de services de localisation. Vous pouvez entrer une chaîne telle que «Emplacement est requirejs pour savoir où vous êtes», ce qui, comme dans iOS 7, peut être localisé dans le fichier InfoPlist.ssortingngs.

entrer la description de l'image ici

Ma solution pouvant ê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]; 

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

 - (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) { NSSsortingng *title; title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" : @"Background location is not enabled"; NSSsortingng *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 URLWithSsortingng:UIApplicationOpenSettingsURLSsortingng]; [[UIApplication sharedApplication] openURL:settingsURL]; } } 

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

info.plist:

 NSLocationUsageDescription I need location NSLocationAlwaysUsageDescription I need location NSLocationWhenInUseUsageDescription I need location 

Ajoutez ceci à votre code

 if (IS_OS_8_OR_LATER) { [locationmanager requestWhenInUseAuthorization]; [locationmanager requestAlwaysAuthorization]; } 

Une erreur commune pour les développeurs Swift:

Assurez-vous d’abord d’append une valeur au plist pour NSLocationWhenInUseUsageDescription ou NSLocationAlwaysUsageDescription .

Si vous ne voyez toujours pas de fenêtre vous demandant l’autorisation, regardez si vous mettez la ligne var locationManager = CLLocationManager() dans la méthode viewDidLoad de votre View View Controller. Si vous le faites, alors même si vous appelez locationManager.requestWhenInUseAuthorization() , rien ne s’affichera. 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.

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

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

Modifiez Info.plist votre application et ajoutez la clé NSLocationAlwaysUsageDescription à la valeur de chaîne qui sera affichée à l’utilisateur (par exemple, We do our best to preserve your battery life. ) We do our best to preserve your battery life.

Si votre application n’a besoin de services de localisation que lorsque l’application est ouverte, remplacez:

requestAlwaysAuthorization avec requestWhenInUseAuthorization et

NSLocationAlwaysUsageDescription avec NSLocationWhenInUseUsageDescription .

Je travaillais sur une application qui a été mise à niveau vers iOS 8 et les services de localisation ont cessé de fonctionner. Vous aurez 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’ NSLocationAlwaysUsageDescription entrée NSLocationAlwaysUsageDescription à votre info.plist:

Entrez la description de l'image ici

Notez que je n’ai pas rempli la valeur pour cette clé. Cela fonctionne toujours, et je ne suis pas concerné parce que c’est une application interne. En outre, il existe déjà un titre demandant d’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 méthode locationManager:didChangeAuthorizationStatus: est appelée:

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

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

Solution avec compatibilité ascendante:

 SEL requestSelector = NSSelectorFromSsortingng(@"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

Solution avec compatibilité descendante qui ne produit pas d’avertissements Xcode:

 SEL requestSelector = NSSelectorFromSsortingng(@"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]; } 

Configurez la clé NSLocationWhenInUseUsageDescription dans votre Info.plist .

Pour iOS version 11.0+ : Configurez la clé NSLocationAlwaysAndWhenInUseUsageDescription dans votre Info.plist . avec d’autres 2 clés.

Ceci est un problème avec ios 8 Ajoutez ceci à votre code

 if (IS_OS_8_OR_LATER) { [locationmanager requestWhenInUseAuthorization]; [locationmanager requestAlwaysAuthorization]; } 

et à info.plist:

  NSLocationUsageDescription I need location NSLocationAlwaysUsageDescription I need location NSLocationWhenInUseUsageDescription I need location 

Pour accéder à l’emplacement utilisateur dans iOS 8, vous devrez append,

 NSLocationAlwaysUsageDescription in the Info.plist 

Cela demandera à l’utilisateur la permission d’obtenir son emplacement actuel.

Pour ceux qui utilisaient Xamarin , je devais append manuellement la clé NSLocationWhenInUseUsageDescription à info.plist car elle n’était pas disponible dans les listes déroulantes de Xamarin 5.5.3 Build 6 ou XCode 6.1 – seul NSLocationUsageDescription était dans la liste, ce qui provoquait le CLLocationManager continuer à échouer en silence.

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

Pour iOS-11 Pour iOS 11, consultez cette réponse: Accès à l’emplacement iOS 11

Besoin d’append deux clés dans plist et de fournir un message comme ci-dessous image:

  1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription 3. NSLocationAlwaysUsageDescription 

entrer la description de l'image ici Pour iOS-10 et ci-dessous:

 NSLocationWhenInUseUsageDescription 

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

Méthodes de délégué

 #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 kCLAuthorizationStatusRessortingcted: case kCLAuthorizationStatusDenied: { // do some error handling } break; default:{ [locationManager startUpdatingLocation]; } break; } } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *location = [locations lastObject]; userLatitude = [NSSsortingng ssortingngWithFormat:@"%f", location.coordinate.latitude] ; userLongitude = [NSSsortingng ssortingngWithFormat:@"%f",location.coordinate.longitude]; [locationManager stopUpdatingLocation]; } 

Procédure rapide

Suivez les instructions ci-dessous:

Pour iOS-11 Pour iOS 11, consultez cette réponse: Accès à l’emplacement iOS 11

Besoin d’append deux clés dans plist et de fournir un message comme ci-dessous image:

  1. NSLocationAlwaysAndWhenInUseUsageDescription 2. NSLocationWhenInUseUsageDescription 3. NSLocationAlwaysUsageDescription 

entrer la description de l'image ici Pour iOS-10 et ci-dessous:

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

Méthodes de délégué

 //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 .Ressortingcted: 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 } 
  // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a ssortingng 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]); } 

Un petit aide pour vous tous qui avez plus d’un fichier Info.plist …

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

Il appenda le tag nécessaire à tous les fichiers Info.plist du répertoire en cours (et des sous-dossiers).

Un autre est:

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

Il appenda votre description à tous les fichiers.

Gardez les informations de Cocoa Keys toujours à scope de main pour ces mises à jour, voici le lien:

https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW26

Prendre plaisir.

J’ai une erreur similaire dans iOS9 (en travaillant avec Xcode 7 et Swift 2): Essayer de démarrer les mises à jour d’emplacement MapKit sans demander d’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 ça marche 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 ça dans info.plist: Information Property List: NSLocationWhenInUseUsageDescription Valeur: App a besoin de serveurs de localisation pour le personnel

Pour accéder à l’emplacement de l’utilisateur dans iOS. Vous devez append deux clés

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

dans le fichier Info.plist.

  NSLocationWhenInUseUsageDescription Because I want to know where you are! NSLocationAlwaysUsageDescription Want to know where you are! 

Voir cette image ci-dessous.

Image Info.plist

  1. Ajoutez la clé NSLocationWhenInUseUsageDescription ou NSLocationAlwaysUsageDescription (utilisation GPS en arrière-plan) avec une chaîne demandant d’utiliser le GPS sur chaque info.plist de chaque cible.

  2. Demandez la permission en exécutant:

    [self initLocationManager: locationManager];

initLocationManager est:

 // 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 figurent pas sur chaque info.plist pour chaque cible, l’application ne demandera pas à l’utilisateur. Le if fournit la compatibilité avec iOS 7 et la méthode respondsToSelector: garantit une compatibilité future plutôt que de simplement résoudre le problème pour iOS 7 et 8.

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

I add those key in InfoPlist.ssortingngs in iOS 8.4, iPad mini 2. It works too. I don’t set any key, like NSLocationWhenInUseUsageDescription , in my Info.plist .


InfoPlist.ssortingngs :

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

Base on this thread , it said, as in iOS 7 , can be localized in the InfoPlist.ssortingngs. In my test, those keys can be configured directly in the file InfoPlist.ssortingngs .

So the first thing you need to do is to add one or both of the > following keys to your Info.plist file:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Both of these keys take a ssortingng which is a description of why you need location services. You can enter a ssortingng like “Location is required to find out where you are” which, as in iOS 7 , can be localized in the InfoPlist.ssortingngs file.


METTRE À JOUR:

I think @IOS ‘s method is better. Add key to Info.plist with empty value and add localized ssortingngs to InfoPlist.ssortingngs .