首先对于定位功能实现的问题,详见这幅帖子,超级全面详细:
【iOS】7.4 定位服务->2.1.2 定位 – 官方框架CoreLocation: CLLocationManager(位置管理器)
一、开启定位权限的配置
iOS定位权限自从iOS8之后就改动很多,出于对用户隐私方面来说,如果要调用GPS模块,就必须经过用户确定,体现在应用弹窗让用户选择。需要在info.plist文件添加3个授权
- a. Privacy – Location When In Use Usage Description (应用使用期间),
- b. Privacy – Location Always Usage Description(始终允许),
- c. Privacy – Location Always and When In Use Usage Description(始终允许,iOS11新增)
在iOS11时,Privacy - Location Always and When In Use Usage Description表示始终允许,Location Always Usage Description在功能上被降级为为“应用使用期间”。
复制代码
如果a,b两项添加到plist里,授权提示有2个选择项
如果a,b,c 全部添加到plist里,授权提示有3个选择项
那么当我们允许应用使用GPS获取位置信息之后,我们在设置-隐私-定位服务 找到自己的应用点进去可以看到如下
upload-images.jianshu.io/upload_imag…
有三个选项: 1.永不 2.使用应用期间 3.始终。
- 永不:不给定位权限
- 使用应用期间:应用在前台运行状态才获取定位信息
- 始终:包括应用在后台也能获取定位信息
一般情况下,在info.plist文件中,将以上三条都配置上.
当然,有的情况下只需两个选择:
-
1.永不 2.使用应用期间
info.plist只设置了NSLocationWhenInUseUsageDescription -
1.永不 2.始终
info.plist只设置了NSLocationAlwaysUsageDescription和NSLocationAlwaysAndWhenInUseUsageDescription (今天在iPhone7 plus iOS12.1.4系统 怎么试都不显示定位选择弹框,不知道咋回事,你们可以尝试下,告知下我结果)。
一般除了导航、运动类App才会用到
二、实现后台定位
对于一些运动类、导航类App,可能计时应用退到了后台也要获取用户的位置信息,该功能的实现我们姑且称为:后台定位。
首先,在TARGETS->Capabilities->Background Modes中,开启开关,并且Location updates选项勾选上。
第一步在info.plist文件中配置好了获取用户隐私权限后,第一次登入App,用户会收到一个定位授权弹窗。根据用户的选择情况,会走CLLocationManagerDelegate协议中的- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status方法。当然,也可以通过CLAuthorizationStatus status = [CLLocationManager authorizationStatus];获取当前用户选择的授权状态,然后进行判断做相应逻辑处理。一般处理如下:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(@"定位: %d",status);
switch (status) {
case kCLAuthorizationStatusNotDetermined:
NSLog(@"用户未做选择");//可以提示跳转到设置
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"定位被限制");
break;
case kCLAuthorizationStatusDenied:
NSLog(@"用户拒绝获取定位");
break;
case kCLAuthorizationStatusAuthorizedAlways:
//用户同意永久访问定位
[self.locationManager requestAlwaysAuthorization];
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
//用户允许使用应用期间访问定位
[self.locationManager requestWhenInUseAuthorization];
break;
default:
break;
}
}
复制代码
三、关于蓝条问题的产生机理和处理办法
这种蓝条问题的产生和解决。
CLLocationManager管理类的配置
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = 100;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([[UIDevice currentDevice] systemVersion].floatValue >= 8) {
/*
有这么一种说法
如果两个请求授权的方法都执行了,会出现以下情况
1.requestWhenInUseAuthorization写在前面,第一次打开程序时请求授权,如果勾选了后台模式,进入后台会出现蓝条提示正在定位。当程序退出,第二次打开程序时requestAlwaysAuthorization 会再次请求授权。之后进入后台就不会出现蓝色状态栏。
2.requestAlwaysAuthorization写在前面, requestWhenInUseAuthorization写在后面,只会在第一次打开程序时请求授权,因为requestAlwaysAuthorization得到的授权大于requestWhenInUseAuthorization得到的授权
*/
[_locationManager requestAlwaysAuthorization];
[_locationManager requestWhenInUseAuthorization];
}
if ([[UIDevice currentDevice] systemVersion].floatValue >= 9) {
/*
allowsBackgroundLocationUpdates:是否允许后台定位,默认为NO,只在iOS9.0之后起作用。
设为YES时,必须保证Background Modes 中的Location updates处于选中状态,否则会抛出异常。
在用户选择仅在使用应用期间获取位置权限的情况下,当应用进入后台,手机桌面顶部是否出现蓝条,这句代码起着关键性作用。
首先,这句代码仅在requestWhenInUseAuthorization状态下才起作用,否则不起作用。当设为YES,就是允许在requestWhenInUseAuthorization此状态下,即使App进入后台,但是没杀死,那么就依然可以后台定位。并且顶部给个蓝条闪烁,目的是在于实时提醒用户:你这个App一直在获取你的位置信息哟,如果你感到不需要继续获取了,就杀死该App吧!所以一直蓝条闪烁。
当设置为NO,就是在requestWhenInUseAuthorization状态下,App进入后台,立即停止后台定位。
*/
_locationManager.allowsBackgroundLocationUpdates = YES;
/*
requestLocation和startUpdatingLocation这两个方法非常类似,都会立即返回结果,将获取的定位信息传递给委托对象的locationManager:didUpdateLocations:消息。
不同点:
startUpdatingLocation:可以持续获取定位。当设备移动的距离超过设定的distanceFilter属性值时,接收器会再次生成一条更新消息。
requestLocation:只产生一次定位信息,在此之后定位服务就停止了。并且:当使用这个方法时,委托对象必须要实现locationManager:didUpdateLocations:和locationManager:didFailWithError:方法。
*/
[_locationManager requestLocation];
} else {
[_locationManager startUpdatingLocation];
}
复制代码
其实在上段代码注释中已经写得较清楚了。
-
蓝条问题的产生前提:只在requestWhenInUseAuthorization这个状态下才会出现。
-
蓝条出现的目的:因为用户选择的是仅在应用使用期间获取位置,所以当app进入后台后,系统将以蓝条闪烁的形式不断提醒用户:主人,某某App一直在后台获取你的位置权限哟,如果你不需要用到了,你就直接将该App杀死吧,不然挺耗电的,如果有需要就当我没说哈。
-
蓝条出现与否的背后代码操控者:_locationManager.allowsBackgroundLocationUpdates = YES;如果不想出现蓝条,直接设置为NO,或者注释,因为默认为NO。
-
另外,蓝条出现与否的另一种说法:跟下面两句代码的执行顺序有关
[_locationManager requestAlwaysAuthorization];
[_locationManager requestWhenInUseAuthorization];
复制代码
详见代码注释。
四、一张很经典的表格
此表早已包罗万象,望各位施主早日参透
告辞!