2017-10-07 31 views
0

我一直在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

回答

1

我有了新的設備的一個報道這個問題,因爲你知道外景經理通常稱此:

- (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