我使用MKUserTrackingBarButtonItem
(即指南针图标)在点击时MKMapView
显示和跟踪用户位置。这在iOS 7中运行良好。在iOS 8中,我开始收到以下消息:
尝试在不提示位置授权的情况下启动MapKit位置更新。必须首先调用 - [CLLocationManager requestWhenInUseAuthorization]或 - [CLLocationManager requestAlwaysAuthorization]。
我了解必须添加以下代码:
if ([self->_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[self->_locationManager requestWhenInUseAuthorization];
}
并且Info.plist文件必须包含:
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
我的问题是在哪里拨打requestWhenInUseAuthorization
。如果我将它放在didChangeUserTrackingMode
中,则为时已晚,我收到上述错误消息。如果我在初始化viewDidLoad
时将其放在CLLocationManager
中,它可以正常工作,但它会改变屏幕的行为,即加载地图时,不会跟踪用户的位置,因此用户只有在点击MKUserTrackingBarButtonItem
按钮时才会收到提示。
答案 0 :(得分:0)
首先为观察者设置静态上下文(将其置于@implementation之上),我们将使用它的地址(&amp;)为我们提供此类的唯一上下文:
static NSString* kShowsUserLocationChanged = @"kShowsUserLocationChanged";
接下来,您需要观察MKMapView的showsUserLocation属性:
[self.mapView addObserver:self
forKeyPath:@"showsUserLocation"
options:(NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
context:&kShowsUserLocationChanged];
然后,您需要一种方法来请求授权,如果之前尚未确定,并且作为奖励,我的方法还会检查Info.plist是否已正确配置,并提醒开发人员是否已经确认。事实并非如此:
-(void)_requestLocationAuthorizationIfNotDetermined{
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
BOOL always = NO;
if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
always = YES;
}
else if(![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]){
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Location usage description missing from Info.plist" userInfo:nil];
}
static CLLocationManager* lm = nil;
static dispatch_once_t once;
dispatch_once(&once, ^ {
// Code to run once
lm = [[CLLocationManager alloc] init];
});
if(always){
[lm requestAlwaysAuthorization];
}else{
[lm requestWhenInUseAuthorization];
}
}
}
最后,您需要添加observe方法实现:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
// if it was our observation
if(context == &kShowsUserLocationChanged){
// if its being enabled
if([[change objectForKey:NSKeyValueChangeNewKey] boolValue]){
[self _requestLocationAuthorizationIfNotDetermined];
}
}
else{
// if necessary, pass the method up the subclass hierarchy.
if([super respondsToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)]){
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
}
您可以通过卸载清除下次部署并运行的授权状态的应用程序来测试它。
答案 1 :(得分:-1)
我在第一次需要时调用requestWhenInUseAuthorization
成功,但随后回复didChangeAuthorizationStatus
开始跟踪。
示例: