title : IOS地图定位导航
category : UI
地图定位导航
标签(空格分隔): IOS
概述
IOS中通过CoreLocation
框架进行定位操作
在IOS开发中,定位
和地图
两个功能是基于CoreLocation
和MapKit
这两个框架来开发
-
CoreLocation:用于地理定位,地理编码,区域监听等(着重功能实现)
-
MapKit:用于地图展示,例如大头针,路线,覆盖层展示等(着重界面展示)
-
两个热门专业术语
- LBS:Location Based Service
- SoLoMo:Social Local Mobile(索罗门):社交化、本地化、移动化
CoreLocation框架的使用
- CoreLocation自身可以单独使用,和MapKit框架是完全独立的两个框架,但实际开发中需要将他们两者结合起来使用
- CoreLocation可以实现定位功能和地理编码与逆地理编码功能
CLLocationManager的常用操作
// 开始更新用户位置
- (void)startUpdatingLocation;
// 停止更新用户位置
- (void)stopUpdatingLocation;
// 当调用了startUpdatingLocation方法后,就开始不断地请求、刷新用户的位置,一旦请求到用户位置就会调用代理的以下方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations;
1 类方法
+ (BOOL)locationServicesEnabled;/* 返回用户是否启用定位服务 */
+ (CLAuthorizationStatus)authorizationStatus;/* 定位服务授权状态,返回枚举类型 */
typedef NS_ENUM(int, CLAuthorizationStatus){
kCLAuthorizationStatusNotDetermined = 0, /* 用户尚未决定是否启用定位服务 */
kCLAuthorizationStatusRestricted, /* 没有获得用户授权 */
kCLAuthorizationStatusDenied, /* 用户禁止使用定位或者定位服务处于关闭状态 */
kCLAuthorizationStatusAuthorizedAlways, /* 前台、后台定位授权 */
kCLAuthorizationStatusAuthorizedWhenInUse, /* 前台定位授权 */
};
2 对象属性
// 每隔多少米定位一次
locationMgr.distanceFilter = 100;
// 定位的精确度
locationMgr.desiredAccuracy = kCLLocationAccuracyHundredMeters;
精确度枚举值(越精确就越耗电)
kCLLocationAccuracyBestForNavigation /* 最适合导航的 */
kCLLocationAccuracyBest; /* 精度最好的 */
kCLLocationAccuracyNearestTenMeters; /* 附近10米 */
kCLLocationAccuracyHundredMeters; /* 附近100米 */
kCLLocationAccuracyKilometer; /* 附近1000米 */
kCLLocationAccuracyThreeKilometers; /* 附近3000米 */
3 对象方法
#pragma mark - 定位追踪
-(void)startUpdatingLocation;/* 开始定位追踪 */
-(void)stopUpdatingLocation;/* 停止定位追踪 */
#pragma mark - 导航追踪
-(void)startUpdatingHeading;/* 开始导航方向追踪 */
-(void)stopUpdatingHeading;/* 停止导航方向追踪 */
#pragma mark - 区域定位追踪
-(void)startMonitoringForRegion:(CLRegion *)region;/* 开始对某个区域进行定位追踪 */
-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止对某个区域进行定位追踪 */
#pragma mark - 授权请求
-(void)requestWhenInUseAuthorization;/* 请求获得应用前台定位授权 */
-(void)requestAlwaysAuthorization;/* 请求获得应用前后台定位授权 */
4. 常用代理方法<CLLocationManagerDelegate>
/* 位置发生改变后调用,第一次定位也会调用 */
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations;
/* 导航方向发生变化后调用 */
-(void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading;
/* 进入某个区域后调用 */
-(void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region;
/* 走出某个区域后调用 */
-(void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region;
/* 当用户授权状态发生变化时调用 */
-(void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
CoreLocation定位功能的使用步骤
- 首先导入头文件
#import <CoreLocation/CoreLocation.h>
IOS8.0之前的定位使用
1.1 前台定位
- (void)viewDidLoad{
[super viewDidLoad];
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服务当前可能尚未打开,请设置打开!");
return;
}
[self initLocationManager];
//调用方法,开始更新用户位置信息
[self.locationM startUpdatingLocation];
}
//创建CLLocationManager并启动定位
- (void)initLocationManager{
//创建CLLocationManager对象并设置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
//设置定位精度和位置更新最小距离
self.locationM.distanceFilter = 100;
self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
//在对应的代理方法中获取位置信息
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation*> *)locations
{
CLLocation *location = [locations firstObject];//取出第一个位置
/*
使用位置前, 务必判断当前获取的位置是否有效
如果水平精确度小于零, 代表虽然可以获取位置对象, 但是数据错误, 不可用
*/
if (location.horizontalAccuracy < 0)
return;
CLLocationCoordinate2D coordinate = location.coordinate;//位置坐标
CGFloat longitude = coordinate.longitude;//经度
CGFloat latitude = coordinate.latitude;//纬度
CGFloat altitude = location.altitude;//海拔
CGFloat course = location.course;//方向
CGFloat speed = location.speed;//速度
NSLog(@"经度:%f,纬度:%f",longitude,latitude);
NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
//如果不需要实时定位,使用完即使关闭定位服务
[self.locationM stopUpdatingLocation];
}
- 1 定位频率和定位精度并不是越精确越好,需要视实际情况而定,因为越精确越耗性能,也就越费电。
- 2 定位成功后会根据设置情况频繁调用locationManager:didUpdateLocations:方法
- 3 每个元素一个CLLocation代表地理位置信息,之所以返回数组是因为有些时候一个位置点可能包含多个位置。
- 4 使用完定位服务后,如果不需要实时监控应该立即关闭定位服务,以节省资源。
- 5 除了提供定位功能,还可以调用startMonitoringForRegion:方法对指定区域进行监控。
1.2 后台定位
在前台的基础上,在项目的Capabilities中的Background Modes打开,并勾选上Location updates。这样就可以开启后台定位模式了
开启后台定位模式.png2 IOS8.0之后
IOS8.0开始,苹果进一步加强了对用户隐私的保护。当APP想访问用户的隐私信息是,系统不再自动弹出一个对话框让用户授权
解决方案:
调用IOS8.0的API,主动请求用户授权
// 请求允许在前后台都能获取用户位置的授权
- (void)requestAlwaysAuthorization;
// 请求允许在前台获取用户位置的授权
- (void)requestWhenInUseAuthorization;
注意
务必需要在Info.plist文件中配置以下对应的键值,否则以上请求授权的方法不会生效。
- (1)始终允许访问位置信息
NSLocationAlwaysUsageDescription
- (2)使用应用程序期间允许访问位置数据
NSLocationWhenInUseUsageDescription
- (void)viewDidLoad{
[super viewDidLoad];
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服务当前可能尚未打开,请设置打开!");
return;
}
[self initLocationManager];
//如果没有授权,则请求用户授权
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined){
//请求前台定位授权
//[self.locationM requestWhenInUseAuthorization];
//请求前后台定位授权
[self.locationM requestAlwaysAuthorization];
}
}
//创建CLLocationManager并启动定位
- (void)initLocationManager{
//创建CLLocationManager对象并设置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
//设置定位精度和位置更新最小距离
self.locationM.distanceFilter = 100;
self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
// 当用户授权状态发生变化时调用
- (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined://用户还未决定
{
NSLog(@"用户还未决定");
break;
}
case kCLAuthorizationStatusRestricted://访问受限
{
NSLog(@"访问受限");
break;
}
case kCLAuthorizationStatusDenied://定位关闭时或用户APP授权为永不授权时调用
{
NSLog(@"定位关闭或者用户未授权");
if ([CLLocationManager locationServicesEnabled]) {
NSLog(@"定位开启,但被拒");
}else{
NSLog(@"定位关闭,不可用");
}
break;
}
case kCLAuthorizationStatusAuthorizedAlways://获取前后台定位授权
{
NSLog(@"获取前后台定位授权");
[self.locationM startUpdatingLocation];
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse://获得前台定位授权
{
NSLog(@"获得前台定位授权");
[self.locationM startUpdatingLocation];
break;
}
default:break;
}
}
//在对应的代理方法中获取位置信息
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation*> *)locations
{
CLLocation *location = [locations firstObject];//取出第一个位置
/*
使用位置前, 务必判断当前获取的位置是否有效
如果水平精确度小于零, 代表虽然可以获取位置对象, 但是数据错误, 不可用
*/
if (location.horizontalAccuracy < 0)
return;
CLLocationCoordinate2D coordinate = location.coordinate;//位置坐标
CGFloat longitude = coordinate.longitude;//经度
CGFloat latitude = coordinate.latitude;//纬度
CGFloat altitude = location.altitude;//海拔
CGFloat course = location.course;//方向
CGFloat speed = location.speed;//速度
NSLog(@"经度:%f,纬度:%f",longitude,latitude);
NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
//如果不需要实时定位,使用完即使关闭定位服务
[self.locationM stopUpdatingLocation];
}
注意
对于IOS8.0以后的提示请求访问用户地理位置的提示需要进行系统适配
- 适配方式一
// 系统适配
if ([self.locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.locationMgr requestAlwaysAuthorization];
}
- 适配方式二:
if ([[UIDevice currentDevice].systemVersion doubleValue]>8.0) {
// 设置前后台授权定位
[self.locationMgr requestAlwaysAuthorization];
// 设置前台授权
[self.locationMgr requestWhenInUseAuthorization];
}
- 对于IOS9.0如果只是开启前台定位,需要手动提示开启后台定位
if ([self.locationMgr respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
// 在IOS9.0以后,需要允许后台获取用户位置
// 注意,这里同时需要勾选后台模式
self.locationMgr.allowsBackgroundLocationUpdates = YES;
}
参考资料:
iOS8中使用CoreLocation定位
网友评论