Avertissement Xcode lors de l'utilisation de MapKit et CoreLocation

J'essaie d'utiliser implémenter une instance de MKMapView , utiliser CoreLocation pour suivre l'location des users, puis zoomer à l'endroit où ils se trouvent.

Je veux seulement suivre l'location de l'user quand je suis au premier plan. Puisque mon application est ciblée pour iOS8, j'ai une input pour la key NSLocationWhenInUseUsageDescription .

Lorsque je lance l'application pour la première fois, l'application request de manière appropriée si elle peut accéder à ma position. Après avoir cliqué sur "Autoriser", je reçois l'avertissement suivant de Xcode:

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

… ce qui est un peu déroutant, car requestWhenInUseAuthorization en fait requestWhenInUseAuthorization , comme on peut le voir dans mon code ci-dessous:

 @property (strong, nonatomic) IBOutlet MKMapView *mapView; @property(nonatomic, retain) CLLocationManager *locationManager; @end @implementation MapView - (void)viewDidLoad { [super viewDidLoad]; [self locationManager]; [self updateLocation]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; self.locationManager = nil; } - (CLLocationManager *)locationManager { //We only want to get the location when the app is in the foreground [_locationManager requestWhenInUseAuthorization]; if (!_locationManager) { _locationManager = [[CLLocationManager alloc] init]; _locationManager.desiredAccuracy = kCLLocationAccuracyBest; } return _locationManager; } - (void)updateLocation { _mapView.userTrackingMode = YES; [self.locationManager startUpdatingLocation]; } 

Quelqu'un at-il un aperçu de la raison pour laquelle cet avertissement se produirait?

Vous appelez requestWhenInUseAuthorization , c'est-à-dire vrai. Mais attendez-vous d' get l' autorisation? Non tu ne l'es pas. Vous (en tant qu'user) tapotez sur Autoriser, mais cela arrive trop tard: votre code a déjà continué, tout droit pour indiquer à la vue cartographique de commencer à suivre l'location de l'user.

Il suffit de regarder les documents sur requestWhenInUseAuthorization :

Lorsque le statut d'autorisation actuel est kCLAuthorizationStatusNotDetermined, cette méthode s'exécute de manière asynchronous

Obtenir cela? Fonctionne de manière asynchronous . Cela signifie que requestr la permission se passe en arrière-plan sur un autre thread.

Et les docs continuent à dire:

Une fois l'état déterminé, le gestionnaire d'location transmet les résultats à la méthode locationManager:didChangeAuthorizationStatus: du délégué locationManager:didChangeAuthorizationStatus: méthode

Donc, implémentez cette méthode. Si vous venez d'get l'autorisation, c'est le signal que vous pouvez commencer à utiliser le gestionnaire de localization.

De plus, il vous manque une étape importante: vous ne vérifiez pas le statut actuel. Vous ne devriez requestr une autorisation que si le statut est indéterminé . Si le statut est restreint ou refusé, vous ne devez absolument pas utiliser le gestionnaire d'location. et si le statut est accordé, il est inutile de requestr à nouveau l'autorisation.

Donc, pour résumer, votre organigramme logique devrait être:

  • Vérifiez le statut.

  • Le statut est-il restreint ou refusé? Arrêtez. Vous ne pouvez pas utiliser les mises à jour d'location ou l'location sur une carte.

  • Le statut est-il accordé? Procéder pour get des mises à jour de localization ou faire un location sur une carte.

  • Le statut est-il indéterminé? Demander l'autorisation et arrêter. Traiter locationManager:didChangeAuthorizationStatus: tant que gestionnaire d'achèvement pour votre request d'autorisation. À ce stade, returnnez au début de l'organigramme!