iOS提供了两个框架用来定位以及地图显示。CoreLocation框架包含的类可以帮助设备确定位置和航向以及使用基于位置的有效信息。MapKit框架未定位提供了户用页面的支持(地图显示),里面包含了地图视图、卫星地图视图以及2D、3D混合视图,并且能够让开发人员管理地图标注和地图覆盖层,前者 用于标注地点(常见的地图大头针),后者用来突出某区域或者路线等。
本期内容:
- CLLocationManager申请定位权限
- CLLocationManager获取用户定位
- CLLocation详细使用,定位数据处理
- GPX虚拟定位文件的使用以及模拟器定位使用
CLLocationManager 定位管理器
简介:CLLocationManager是用于启动和停止向App获取位置相关的事件的对象。
只有在得到用户许可的情况下,App才能获取设备的当前位置,但是在获取设备位置之前,App还必须确保设备启动了定位服务,当满足这些条件后,App就可以获取启动位置请求的权限并获取当前位置。
CLLocationManager申请定位权限
那我们就开始了,首先要去项目的target里设置info.plist文件字段(苹果的隐私安全需求,不添加是不允许使用的),如下图标注的三个字段:
接下来我们开始敲代码,创建一个定位管理器CLLocationManager,但是刚刚我们也说过了,如果系统没有打开定位服务,那么我们获得授权也是没用的,所以,首先判断设备是否打开了定位服务:
if ([self checkLocationServiceIsEnabled]) {
[self createCLManager];
}
检查的内部实现:
- (BOOL)checkLocationServiceIsEnabled{
if ([CLLocationManager locationServicesEnabled]) {
return YES;
}
UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"系统定位尚未打开,请到【设定-隐私】中手动打开" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * tipsAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil];
[alertVC addAction:tipsAction];
[self presentViewController:alertVC animated:YES completion:nil];
return NO;
}
创建定位管理器内部实现:
- (void)createCLManager{
self.locaationManager = [[CLLocationManager alloc]init];
[self.locaationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locaationManager setDistanceFilter:100.f];
self.locaationManager.delegate = self;
[self.locaationManager startUpdatingLocation];
}
在这里说一下定位的精准度,这是一个枚举,具体的有以下方式:
精准度枚举 | 作用 |
---|
kCLLocationAccuracyBestForNavigation | 最佳精确度(汽车导航使用) |
kCLLocationAccuracyBest | 最佳精确度 |
kCLLocationAccuracyNearestTenMeters | 10米误差 |
kCLLocationAccuracyHundredMeters | 百米误差 |
kCLLocationAccuracyKilometer | 千米误差 |
kCLLocationAccuracyThreeKilometers | 三千米误差 |
这会儿我们的定位管理器就创建好了,但是到了这一步还是没法使用定位,因为,用户还没有授权给我们的App获取定位权限,所以这会儿我们就需要去主动给用户通知,让用户授权,使用的是CLLocationManager的代理方法:
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
switch (status) {
case kCLAuthorizationStatusNotDetermined:{
NSLog(@"用户还未决定授权");
[self.locaationManager requestWhenInUseAuthorization];
break;
}
case kCLAuthorizationStatusRestricted:
{
NSLog(@"访问受限");
[self.locaationManager requestWhenInUseAuthorization];
break;
}
case kCLAuthorizationStatusDenied:{
if ([CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服务开启,被拒绝");
} else {
NSLog(@"定位服务关闭,不可用");
}
break;
}
case kCLAuthorizationStatusAuthorizedAlways:{
NSLog(@"获得前后台授权");
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse:{
NSLog(@"获得前台授权");
break;
}
default:
break;
}
}
在上述方法中,我们使用[self.locaationManager requestWhenInUseAuthorization]去主动获得授权,但也需要注意里面的两个场景是无法获得授权的。
完成了以上步骤,我们就可以获得权限了,然后我们开始去获得定位
CLLocationManager获取用户定位
CLLocationManager在获取定位的时候是通过代理方法实现的,该方法包装了类型为CLLocation的定位数据数组,并返回给代理中,具体实现如下:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
CLLocation * newLocation = [locations lastObject];
if (newLocation.horizontalAccuracy < 0) {
UIAlertController * alertVC = [UIAlertController alertControllerWithTitle:@"提示" message:@"定位错误,请检查手机网络以及定位" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * tipsAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil];
[alertVC addAction:tipsAction];
[self presentViewController:alertVC animated:YES completion:nil];
return;
}
CLLocationCoordinate2D coor2D = newLocation.coordinate;
NSLog(@"纬度为:%f, 经度为:%f", coor2D.latitude, coor2D.longitude);
CLLocationDistance altitude = newLocation.altitude;
NSLog(@"高度为:%f", altitude);
CLLocationAccuracy horizontalAcc = newLocation.horizontalAccuracy;
CLLocationAccuracy verticalAcc = newLocation.verticalAccuracy;
NSLog(@"%f, %f", horizontalAcc, verticalAcc);
[self.locaationManager stopUpdatingLocation];
}
运行效果如下:
这样我们的位置信息就获取完成了,可能大家看到了,在这个位置信息获取完成之后为什么要写上一个停止更新位置呢?在此我就来解答依稀,一般来说苹果建议我们在获取完位置之后就停止定位,因为电量的消耗是非常大的,但如果我们需要,可以使用以下方法:
[self.locaationManager startMonitoringSignificantLocationChanges]
该方法可以说是一个重大变化通知,避免了随时定位的耗电,当设备检查到数据变化大,就主动调起didUpdateLocations方法来完成位置的改变。
CLLocation详细使用,定位数据处理
在上面我们看到了一个类:CLLocation。和CLLocationManager很像是吧?官方有话说:CLLocation对象包含设备的地理位置和高度,以及指示这些测量值的准确性和收集时间的值。在iOS中,位置对象还包含航向信息,即设备移动的速度和方向。
那我们如何来获得这些信息呢?上代码:
- (void)learningCLLocation{
}
已经很详细的表达出来啦,这些数据可能会有用,希望大家能记下来。虽然我们已经获取了定位的数据,但这些数据我们确实看着不懂,那我们该怎么办呢?苹果提供了一个CLGeocoder类,这个类是用于在地理坐标和地名之间转换的接口,也就是常说的逆地理编码(反地理编码)
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark *placeMark in placemarks) {
NSLog(@"位置:%@", placeMark.name);
NSLog(@"街道:%@", placeMark.thoroughfare);
NSLog(@"子街道:%@", placeMark.subThoroughfare);
NSLog(@"市:%@", placeMark.locality);
NSLog(@"区\\县:%@", placeMark.subLocality);
NSLog(@"行政区:%@", placeMark.administrativeArea);
NSLog(@"国家:%@", placeMark.country);
}
}];
实现之后效果如下:
这样我们的当前定位数据就是很直观的展现出来啦。
GPX虚拟定位文件的使用以及模拟器定位使用
当我们没有真机调试或者需要进行简单的定位调试的时候,我们会使用GPX虚拟定位文件或者直接使用模拟器的定位工具,可能有的小伙伴不太懂,我这里就给大家讲一下:
- GPX虚拟定位文件
首先在工程中 cmd + n 打开文件创建页面,找到gpx文件,如图:
然后在选择运行设备的地方选择 Eidt Scheme,按照下图方式进行操作:
然后就会在项目中发现我们的GPX虚拟定位文件啦,之后我们在该文件里面作出修改,运行项目,就可以获得目标位置的信息,修改文件内容如下图:
把lat和lng以及name修改就行,时间戳不用修改,这样我们的GPX虚拟定位文件就添加好并可以使用了,使用方式直接选择模拟器运行就可以。如果说GPX文件操作比较繁琐和复杂,我们还可以使用模拟器的工具来进行定位修改,如图:
然后输入目标经纬度就可以完成位置录入了。
补充说明:
之前面试的时候谈及耗电量优化,在新的API中,苹果提供了单次定位请求的功能,也就是获取一次位置信息,代码:
[self.locaationManager requestLocation]
其实现逻辑是按照定位精确度从低到高进行排序,逐个进行定位。如果在有效时间内,定位到了精确度最好的位置,那么就把对应的位置通过代理告知外界,如果获取到的位置不是精确度最高的那个,也会在定位超时后,通过代理告诉我们。需要注意的是:必须实现代理的locationManager:didFailWithError:方法,不能与startUpdatingLocation方法同时使用。
实现如下:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(@"%@",error);
[self.locaationManager stopUpdatingLocation];
}
好了这期的内容到这里就结束了,下期就开讲原生的MapKit,到时候直接是可视化的地图定位信息,大家伙期待吗?~
下期内容:MapKit的实际应用
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)