iOS 11 – La mise à jour d'location n'a pas été reçue après l'ajout d'un délégué

J'ai eu des problèmes avec les services de localization dans iOS 11 à la fois pour "Autoriser en cours d'utilisation" et "Toujours autoriser". Fonctionne sans problème dans iOS <11. Suivi ce fil en essayant de réparer mais ne fonctionne toujours pas. Qu'est-ce que je rate? Merci d'avance.

  1. J'ai UITabViewController dans mon application et un UINavigationController dans chaque onglet.
  2. J'ai une class LocationManager singleton. Je configure le RootViewController de mon UINavigationController en tant que délégué de viewWillAppear de viewWillAppear pour recevoir les mises à jour d'location et les supprimer dans viewWillDisappear .
  3. Maintenant, lorsque je lance l'application, avant que la barre d'tabs ne soit créée, je peux voir que la mise à jour de l'location est appelée dans la class LocationManager.
  4. Mais quand j'ajoute mon UIViewController en tant que délégué et donne startUpdatingLocation je ne reçois pas la mise à jour d'location dans mon UIVIewController.
  5. Ensuite, j'appuie sur le button Accueil et quitte l'application. Encore une fois lancer immédiatement l'application et je reçois la mise à jour de l'location dans ma méthode de délégué.

J'ai ajouté les trois descriptions d'autorisation d'location dans mon file Info.plist.

Info.Plist:

 <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <ssortingng>Blah Blah Blah</ssortingng> <key>NSLocationAlwaysUsageDescription</key> <ssortingng>Blah Blah Blah</ssortingng> <key>NSLocationWhenInUseUsageDescription</key> <ssortingng>Blah Blah Blah</ssortingng> 

LocationController.m:

 #import "LocationController.h" //static int LOCATION_ACCESS_DENIED = 1; //static int LOCATION_NETWORK_ISSUE = 2; //static int LOCATION_UNKNOWN_ISSUE = 3; enum { LOCATION_ACCESS_DENIED = 1, LOCATION_NETWORK_ISSUE = 2, LOCATION_UNKNOWN_ISSUE = 3 }; static LocationController* sharedCLDelegate = nil; @implementation LocationController int distanceThreshold = 10.0; // in meters @synthesize locationManager, currentLocation, locationObservers; - (id)init { self = [super init]; if (self != nil) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; self.locationManager.distanceFilter = distanceThreshold; self.locationManager.pausesLocationUpdatesAutomatically = NO; [self.locationManager startMonitoringSignificantLocationChanges]; self.locationManager.delegate = (id)self; if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { [self.locationManager requestWhenInUseAuthorization]; //I sortinged both commenting this line and uncommenting this line. Didn't make any difference } if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { [self.locationManager requestAlwaysAuthorization]; } [self.locationManager startUpdatingLocation]; [self.locationManager startUpdatingHeading]; locationObservers = [[NSMutableArray alloc] init]; } return self; } #pragma mark - #pragma mark CLLocationManagerDelegate Methods - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { NSLog(@"locationManager didUpdateLocations = %@",locations); CLLocation *newLocation = [locations lastObject]; if (newLocation.horizontalAccuracy < 0) { return; } currentLocation = newLocation; for(id<LocationControllerDelegate> observer in self.locationObservers) { if (observer) { // CLLocation *newLocation = [locations lastObject]; // if (newLocation.horizontalAccuracy < 0) { // return; // } // currentLocation = newLocation; NSTimeInterval interval = [currentLocation.timestamp timeIntervalSinceNow]; //check against absolute value of the interval if (fabs(interval)<30) { [observer locationUpdate:currentLocation]; } } } } - (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error { NSLog(@"locationManager didFailWithError: %@", error); for(id<LocationControllerDelegate> observer in self.locationObservers) { if (observer) { [observer failedToGetLocation:error]; } } switch (error.code) { case kCLErrorDenied: { break; } case kCLErrorNetwork: { break; } default: break; } } #pragma mark - Singleton implementation in ARC + (LocationController *)sharedLocationInstance { static LocationController *sharedLocationControllerInstance = nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^{ sharedLocationControllerInstance = [[self alloc] init]; }); return sharedLocationControllerInstance; } -(void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { NSLog(@"didChangeAuthorizationStatus = %i",status); if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { [self.locationManager stopUpdatingLocation]; [self.locationManager startUpdatingLocation]; } } - (void) addLocationManagerDelegate:(id<LocationControllerDelegate>)delegate { if (![self.locationObservers containsObject:delegate]) { [self.locationObservers addObject:delegate]; } [self.locationManager startUpdatingLocation]; } - (void) removeLocationManagerDelegate:(id<LocationControllerDelegate>)delegate { if ([self.locationObservers containsObject:delegate]) { [self.locationObservers removeObject:delegate]; } } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if (sharedCLDelegate == nil) { sharedCLDelegate = [super allocWithZone:zone]; return sharedCLDelegate; // assignment and return on first allocation } } return nil; // on subsequent allocation attempts return nil } - (id)copyWithZone:(NSZone *)zone { return self; } #pragma mark UIAlertViewDelegate Methods - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case LOCATION_ACCESS_DENIED: { if (buttonIndex == 1) { //[[UIApplication sharedApplication] openURL: [NSURL URLWithSsortingng: UIApplicationOpenSettingsURLSsortingng]]; [[UIApplication sharedApplication] openURL:[NSURL URLWithSsortingng:@"prefs:root=LOCATION_SERVICES"]]; } } break; case LOCATION_NETWORK_ISSUE: break; case LOCATION_UNKNOWN_ISSUE: break; default: break; } [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES]; } @end 

LocationController.h

 #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> #import <Foundation/Foundation.h> // protocol for sending location updates to another view controller @protocol LocationControllerDelegate @required - (void)locationUpdate:(CLLocation*)location; - (void)failedToGetLocation:(NSError*)error; @end @interface LocationController : NSObject<CLLocationManagerDelegate,UIAlertViewDelegate> @property (nonatomic, strong) CLLocationManager* locationManager; @property (nonatomic, strong) CLLocation* currentLocation; @property (strong, nonatomic) NSMutableArray *locationObservers; + (LocationController*)sharedLocationInstance; // Singleton method - (void) addLocationManagerDelegate:(id<LocationControllerDelegate>) delegate; - (void) removeLocationManagerDelegate:(id<LocationControllerDelegate>) delegate; @end 

ViewController.m

 - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSLog(@"VC viewWillAppear"); [locationControllerInstance addLocationManagerDelegate:self]; } 

AppDelegate.m

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [LocationController sharedLocationInstance]; } 

L'un des nouveaux périphériques a signalé ce problème, car vous savez que le gestionnaire de position appelle généralement ceci:

– (void) mapView: (MKMapView *) mapView didUpdateUserLocation: (MKUserLocation *) userLocation

Ce qui est bizarre, c'est que l'object UserLocation contient deux objects de coordonnées:

1) userLocation.location.coordinate: Cela fonctionne très bien, mais pour une raison quelconque, il returnne NULL sur IOS11 sur certains appareils (on ne sait pas encore pourquoi ou comment cela se comporte depuis IOS11).

2) userLocation.coordinate: Ceci est un autre (même) object que vous pouvez voir à partir des propriétés, il a datatables de localization et continue à fonctionner correctement avec IOS11, cela ne semble pas être (encore) brisé.

Donc, avec l'exemple ci-dessus, "je suppose" que votre:

  • (vide) locationManager: gestionnaire (CLLocationManager *) didUpdateLocations: locations (NSArray *)

Peut-être que le problème est le même (ie le tableau peut renvoyer une valeur nulle quelque part dans l'object location, mais pas l'object coordonnée, la solution que j'ai faite sur mon code qui obtient un location à la fois est maintenant fixée en remplaçant userLocation. location.coordinate avec userLocation.coordinate, et le problème est parti.

Je colle également ma fonction ci-dessous pour vous aider, j'espère que cela vous aidera à résoudre le vôtre, notez que j'ai deux conditions pour tester l'un pour searchr l'object location et l'autre pour l'object de coordonnées, l'autre semble être cassé dans IOS11:

 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { Log (4, @"MapView->DidUpdateUL - IN"); if (_OrderStartTrackingMode == enuUserMapTrackingMode_User) { if (userLocation) { if (userLocation.location) { if ( (userLocation.location.coordinate.latitude) && (userLocation.location.coordinate.longitude)) { [_mapLocations setCenterCoordinate:userLocation.location.coordinate animated:YES]; } else { if ( (userLocation.coordinate.latitude) && (userLocation.coordinate.longitude)) { [self ShowRoutePointsOnMap:userLocation.coordinate]; } } } } } else if (_OrderStartTrackingMode == enuUserMapTrackingMode_Route) { if (userLocation) { if ( (userLocation.coordinate.latitude) && (userLocation.coordinate.longitude)) { [self ShowRoutePointsOnMap:userLocation.coordinate]; } } } Log (4, @"MapView->DidUpdateUL - OUT"); } 

Inutile de dire que si vous avez vérifié vos parameters pour l'object Carte, vous devriez avoir au less "Emplacement de l'user" activé:

entrez la description de l'image ici

PS La fonction Log sur le code ci-dessus est un wrapper à la fonction NSLog, car j'utilise le mien pour écrire aussi dans des files.

Bonne chance Uma, laissez-moi savoir comment ça se passe.

Cordialement, Heider