声明
因为苹果在不允许使用第三方库进行定位,即使是百度地图的定位也是在苹果API的基础上进行了封装,所以学习下iOS中定位的功能还是有必要的
CoreLocation框架
- CLLocationManager是一个非常重要的对象
各系统版本的前台跟后台访问权限
- iOS8之前
如果想要定位需要在plist文件中位置key Privacy - Location Usage Description(NSLocationUsageDescription
),默认只在前台定位,如果想开启后台定位需要在开启后台模式
717775-cc91e37a8c114e7a.png
iOS8+
iOS 8.0开始,苹果进一步加强了对用户隐私的保护
当APP想访问用户的隐私信息时,系统不再自动弹出一个对话框让用户授权
我们需要调用iOS 8.0的API,主动请求用户授权(void)requestAlwaysAuthorization // 请求允许在前后台都能获取用户位置的授权
(void)requestWhenInUseAuthorization // 请求允许在前台获取用户位置的授权
注意:务必在info.plist文件中配置对应的键值, 否则以上请求授权的方法不生效
● NSLocationAlwaysUsageDescription : 允许在前后台获取GPS的描述
● NSLocationWhenInUseDescription : 允许在前台获取GPS的描述
注意: 如果是前台定位权限,但是开启了后台模式,在后台也是可以定位的,但是屏幕的上边会有蓝条,提示用户是哪个应用在定位
- iOS 9
如果想要在后台定位,除了配置NSLocationAlwaysUsageDescription(前后台定位)外,还需要手动设置allowsBackgroundLocationUpdates = YES, 否则 后台不会定位
#pragma mark - CLLocationManager懒加载
- (CLLocationManager *)lM
{
if (!_lM) {
// 1. 创建位置管理者
_lM = [[CLLocationManager alloc] init];
// 1.1 代理, 通知, block
_lM.delegate = self;
_lM.desiredAccuracy = kCLLocationAccuracyBest;
if([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)
{
[_lM requestAlwaysAuthorization];
}
// 允许后台获取用户位置(iOS9.0)
if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0)
{
// 一定要勾选后台模式 location updates 否者程序奔溃
_lM.allowsBackgroundLocationUpdates = YES;
}
}
return _lM;
}
注意:只要是想后台获取用户的位置,就必须开启后台模式 项目->TARGETS->Capabilities-> Background Modes 勾线 Location updates
CLLocationManager的一些属性
kCLLocationAccuracyBestForNavigation // 最适合导航
kCLLocationAccuracyBest; // 最好的
kCLLocationAccuracyNearestTenMeters; // 10m
kCLLocationAccuracyHundredMeters; // 100m
kCLLocationAccuracyKilometer; // 1000m
kCLLocationAccuracyThreeKilometers; // 3000m
// 设置定位的精确度
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
// 每隔多米定位一次 eg._lM.distanceFilter = 30;
@property(assign, nonatomic) CLLocationDistance distanceFilter;
CLLocationManagerDelegate
#pragma mark - CLLocationManagerDelegate
// 用户的位置更新之后调用
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
/*
经纬度
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
海拔
@property(readonly, nonatomic) CLLocationDistance altitude;
航向
@property(readonly, nonatomic) CLLocationAccuracy course;
速度
@property(readonly, nonatomic) CLLocationSpeed speed
*/
CLLocation *location = locations.firstObject;
NSLog(@"%f", location.coordinate.longitude);
}
// 授权状态发生改变时调用
// 第一次弹出请求定位权限会执行该代码块 用户如果点击 "不允许" 执行"定位开启,但被拒", 若点击 "允许" 执行 获取前后台定位授权 或者 获取前后台定位授权 如果在设置 设置隐私 定位服务 "永不" 则执 "行定位开启,但被拒"
// 注意:在设置点击了"永不"之后不返回应用在切换后台跟前台选项是不会执行该代理方法的 当返回应用之后 才会对做出的改变执行代理方法
// 关闭定位服务会执行 定位关闭,"不可用" 系统默认弹出弹框 提示用户去设置中打开定位服务选项
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
// 用户还未决定
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用户还未决定");
break;
}
// 访问受限
case kCLAuthorizationStatusRestricted:
{
NSLog(@"访问受限");
break;
}
// 定位关闭时和对此APP授权为never时调用
case kCLAuthorizationStatusDenied:
{
// 定位是否可用(是否支持定位或者定位是否开启)
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位开启,但被拒");
}else
{
NSLog(@"定位关闭,不可用, 请在设置中打开定位服务选项");
}
// NSLog(@"被拒");
break;
}
// 获取前后台定位授权
case kCLAuthorizationStatusAuthorizedAlways:
// case kCLAuthorizationStatusAuthorized: // 失效,不建议使用
{
NSLog(@"获取前后台定位授权");
break;
}
// 获得前台定位授权
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"获得前台定位授权");
break;
}
}
}