iOS 11 - 添加代理后未收到位置更新

问题描述:

我一直在iOS 11中的“允许使用”和“始终允许”位置服务遇到问题。 iOS中的问题没有问题< 11.在尝试修复时遵循此thread,但仍然无效。我错过了什么?先谢谢你。iOS 11 - 添加代理后未收到位置更新

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

我在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]; 
} 
+0

我没有考虑你的问题,但它总是很好看[最新的核心位置WWDC视频](https://www.google.com/search?q=wwdc + 2017 + +核心位置和OQ = WWDC + 2017 + +核心失水&AQS = chrome.0.0j69i57.3918j0j7&的SourceID =铬&即= UTF-8)。你有看到它吗? – Honey

+0

@Honey不,我没有。正在看。感谢链接 – Uma

+0

@Honey我刚看完了。我不认为还有什么我错过了。此外,后台位置服务不需要,因此不启用。我想,我没有启用它。我的问题不同于“未收到更新”。我收到更新。但我只能在应用程序进入后台并重新打开之后。 – Uma

我有了新的设备的一个报道这个问题,因为你知道外景经理通常称此:

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

的奇怪的事情是,用户位置对象包含两个坐标对象:

1)userLocation.location.coordinate:这用来做工精细,但由于某种原因它在某些设备上IOS11返回NULL(它是不知道为什么自IOS11以来这是行为的)。

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

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

  • (无效)的LocationManager:(CLLocationManager *)经理didUpdateLocations:(NSArray的*)位置

可能会遇到同样的问题(即数组可能在位置对象的某个位置返回空值,但不是坐标对象,我一次只获取一个位置的代码所做的解决方案现在可以通过替换userLocation .location.coor dinate与userLocation.coordinate,并且问题消失了。

我也粘贴下面的函数来进一步帮助你,希望它能帮助你解决你的问题,注意到我有两个条件用于测试一个用于获取位置对象,另一个用于获取坐标对象,一个用于测试现在罚款,对方似乎在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对象,你至少应该有“用户位置”已启用:

enter image description here

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

祝你好运乌玛,让我知道它是怎么回事。

问候,海德

+0

Heider,非常感谢您的详细解答。我刚刚根据@ Paulw11发表的评论解决了这个问题。正如你所提到的那样,在很少的设备中,位置更新被接收到,但是我已经决定将它添加到我的代码中来解决这个问题。伟大的发现! – Uma