iOS 11 - 添加代理后未收到位置更新
我一直在iOS 11中的“允许使用”和“始终允许”位置服务遇到问题。 iOS中的问题没有问题< 11.在尝试修复时遵循此thread,但仍然无效。我错过了什么?先谢谢你。iOS 11 - 添加代理后未收到位置更新
- 我在我的应用程序
UITabViewController
和UINavigationController
每个选项卡内。 - 我有一个singleton LocationManager类。我将我的UINavigationController的RootViewController设置为委托ViewController的
viewWillAppear
来接收位置更新并在viewWillDisappear
中删除。 - 现在,当我启动应用程序时,在创建标签栏之前,我可以看到LocationManager类中正在调用位置更新。
- 但是,当我添加我的UIViewController作为委托,并给
startUpdatingLocation
我没有收到我的UIVIewController中的位置更新。 - 然后我按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];
}
我有了新的设备的一个报道这个问题,因为你知道外景经理通常称此:
- (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对象,你至少应该有“用户位置”已启用:
P.S.上面代码中的Log函数是NSLog函数的一个包装,因为我也使用它来写入文件。
祝你好运乌玛,让我知道它是怎么回事。
问候,海德
Heider,非常感谢您的详细解答。我刚刚根据@ Paulw11发表的评论解决了这个问题。正如你所提到的那样,在很少的设备中,位置更新被接收到,但是我已经决定将它添加到我的代码中来解决这个问题。伟大的发现! – Uma
我没有考虑你的问题,但它总是很好看[最新的核心位置WWDC视频](https://www.google.com/search?q=wwdc + 2017 + +核心位置和OQ = WWDC + 2017 + +核心失水&AQS = chrome.0.0j69i57.3918j0j7&的SourceID =铬&即= UTF-8)。你有看到它吗? – Honey
@Honey不,我没有。正在看。感谢链接 – Uma
@Honey我刚看完了。我不认为还有什么我错过了。此外,后台位置服务不需要,因此不启用。我想,我没有启用它。我的问题不同于“未收到更新”。我收到更新。但我只能在应用程序进入后台并重新打开之后。 – Uma