【问题标题】:Prompt for Location Authorisation Only When MKUserTrackingBarButtonItem Is Tapped仅在点击 MKUserTrackingBarButtonItem 时提示位置授权
【发布时间】:2014-09-30 14:42:36
【问题描述】:

我正在使用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 中,为时已晚,我会收到上述错误消息。如果我在初始化CLLocationManager 时将它放在viewDidLoad 中,它可以正常工作,但它会改变屏幕的行为,即在加载地图时,不会跟踪用户的位置,因此用户应该只有在MKUserTrackingBarButtonItem 按钮被点击。

【问题讨论】:

    标签: objective-c ios8 mapkit cllocationmanager


    【解决方案1】:

    首先为观察者设置一个静态上下文(将它放在你的@implementation 上方),我们将使用它的地址(&)为我们提供这个类的唯一上下文:

    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];
            }
        }
    }
    

    您可以通过卸载应用程序来测试它,这会清除下一次部署和运行的授权状态。

    【讨论】:

      【解决方案2】:

      我已经成功地在第一次需要时将呼叫发送到 requestWhenInUseAuthorization,然后回复 didChangeAuthorizationStatus 以开始跟踪。

      例子:

      https://github.com/mapbox/mapbox-ios-sdk/blob/509fa7df46ebd654d130ab2f530a8e380bf2bd59/MapView/Map/RMMapView.m#L3299-L3323

      https://github.com/mapbox/mapbox-ios-sdk/blob/509fa7df46ebd654d130ab2f530a8e380bf2bd59/MapView/Map/RMMapView.m#L3746-L3753

      【讨论】:

      • 虽然它不使用MKUserTrackingBarButtonItem。我希望在用户点击 MKUserTrackingBarButtonItem 时出现提示。
      • 我不肯定它会起作用,但尝试子类化 MKMapView 以覆盖 setUserTrackingMode:animated: 以介于按钮和地图属性更改之间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      相关资源
      最近更新 更多