iOS 11 – 添加委托之后,未收到位置更新

我一直在使用“允许使用”和“始终允许”在iOS 11中的位置服务遇到问题。 工作没有问题在iOS <11.跟随这个线程试图修复,但仍然无法正常工作。 我错过了什么? 先谢谢你。

  1. 我有UITabViewController在我的应用程序和每个选项卡内的UINavigationController
  2. 我有一个单身的LocationManager类。 我将我的UINavigationController的RootViewController设置为委托ViewController的viewWillAppear来接收位置更新并在viewWillDisappear移除。
  3. 现在,当我启动应用程序,在创build标签栏之前,我可以看到LocationManager类中正在调用位置更新。
  4. 但是,当我添加我的UIViewController作为委托,并给startUpdatingLocation我没有收到位置更新在我的UIVIewController。
  5. 然后我按Homebutton并退出应用程序。 再次立即启动应用程序,我得到我的委托方法的位置更新。

我在Info.plist文件中添加了全部三个位置授权说明。

info.plist中:

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

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 tried 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 URLWithString: UIApplicationOpenSettingsURLString]]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"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]; } 

我有一个新设备报告了这个问题,因为您知道位置pipe理器通常会这样调用:

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

奇怪的是,UserLocation对象包含两个坐标对象:

1)userLocation.location.coordinate:这用于正常工作,但由于某种原因,它在某些设备上的IOS11上返回NULL(这是未知的,为什么或自IOS11以来如何performance)。

2)userLocation.coordinate:这是另一个(相同)的对象,你可以从属性中看到,它有位置数据,并继续与IOS11罚款,这似乎并没有被打破(还)。

所以,用上面的例子,“我猜”你的:

  • (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

可能会有同样的问题(即数组可能会在位置对象的某个位置返回一个NULL,但不是坐标对象,我一次获取一个位置的代码所做的解决scheme,现在通过replaceuserLocation来解决。 location.coordinate与userLocation.coordinate,问题就消失了。

我也粘贴下面的函数来帮助你进一步,希望它也能帮助你解决你的问题,注意我有两个条件来testing一个用于获取位置对象,另一个用来获取坐标对象,现在工作正常,另一个似乎在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"); } 

不用说,你是否检查过你的Map对象设置,你至less应该启用“User Location”:

在这里输入图像说明

PS上面代码中的Log函数是NSLog函数的一个包装,因为我也用它来写入文件。

祝你好运乌玛,让我知道如何去。

问候,Heider