仅在点击MKUserTrackingBarButtonItem时提示位置授权

时间:2014-09-30 14:42:36

标签: objective-c ios8 mapkit cllocationmanager

我使用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按钮时才会收到提示。

2 个答案:

答案 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)