仅在点击 MKUserTrackingBarButtonItem 时提示位置授权
Posted
技术标签:
【中文标题】仅在点击 MKUserTrackingBarButtonItem 时提示位置授权【英文标题】:Prompt for Location Authorisation Only When MKUserTrackingBarButtonItem Is Tapped 【发布时间】: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
按钮被点击。
【问题讨论】:
【参考方案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:
以介于按钮和地图属性更改之间。以上是关于仅在点击 MKUserTrackingBarButtonItem 时提示位置授权的主要内容,如果未能解决你的问题,请参考以下文章