前言
在iOS开发中,定位和地图功能是比较常用的功能之一,要想加入这2大功能,必须基于2个框架进行开发。
(1) CoreLocation:用于地理定位,地理编码,区域监听等(着重功能实现)。
(2) MapKit:用于地图展示,例如大头针,路线、覆盖层展示等(着重界面展示)。
这篇文章我们来着重的介绍下CoreLocation框架
简介
CoreLocaiton框架是百度地图的定位也是在苹果API的基础上进行了封装。
CoreLocation框架使用前提
导入框架(Xcode5.0之后可以省略)
一 . iOS8.0之前的定位配置
1. 前台定位
直接引入头文件设置代理即可
2.后台定位
需要在前台定位基础上, 勾选后台模式Location updates
二 . iOS8.0之后的定位配置
1. 前台定位
请求前台定位授权, 并在Info.Plist文件中配置Key ( Nslocationwheninuseusagedescription )
参数类型为字符串 如果输入内容则是提示用户的内容
2.后台定位
第一种解决方案
请求前后台定位授权,并在info.plist文件中配置KEY ( NSLocationAlwaysUsageDescription )
第二种解决方案
需要在前台定位基础上, 勾选后台模式Location updates
导入主头文件
#import<CoreLocation/CoreLocation.h>
CoreLocation框架使用前须知
CoreLocation框架中所有数据类型的前缀都是CL
CoreLocation中使用CLLocationManager对象来做用户定位
定位服务
<CLLocationManagerDelegate>需要遵守这个代理
开始更新用户位置-(void)startUpdatingLocation;
停止更新用户位置
-(void)stopUpdatingLocation;
当调用了startUpdatingLocation方法后,就开始不断地请求、刷新用户的位置,一旦请求到用户位置就会调用代理的下面方法
-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations;
locations参数里面装着CLLocation对象(下面我会详细介绍CLLocation对象)
为了严谨起见,最好在使用定位功能之前判断当前应用的定位功能是否可用
CLLocationManager有个类方法可以判断当前应用的定位功能是否可用
+(BOOL)locationServicesEnabled;
@property(assign,nonatomic)CLLocationDistancedistanceFilter;
每隔多少米定位一次
@property(assign,nonatomic)CLLocationAccuracydesiredAccuracy;
定位精确度(越精确就越耗电)
CLLocation对象
CLLocation用来表示某个位置的地理信息,比如经纬度、海拔等等
@property(readonly,nonatomic)CLLocationCoordinate2Dcoordinate; //经纬度
注:
typedef struct
{
CLLocationDegreeslatitude;//纬度
CLLocationDegreeslongitude;//经度
} CLLocationCoordinate2D
@property(readonly,nonatomic)CLLocationDistancealtitude; //海拔
@property(readonly,nonatomic)CLLocationDirectioncourse; //路线,航向(取值范围是0.0°~359.9°,0.0°代表真北方向)
@property(readonly,nonatomic)CLLocationSpeedspeed; //移动速度(单位是m/s)
调用-(CLLocationDistance)distanceFromLocation:(constCLLocation*)location方法可以计算2个位置之间的距离
实例代码
#import "ViewController.h"#import@interface ViewController ()//位置管理者
@property (nonatomic,strong) CLLocationManager *locManager;
@end
@implementation ViewController
//懒加载
- (CLLocationManager *)locManager{
if (!_locManager) {
//创建位置管理者
_locManager = [[CLLocationManager alloc] init];
//代理
_locManager.delegate = self;
//每隔多少米定位移一次
_locManager.distanceFilter = 3000;
// 精确度越高, 越耗电, 定位时间越长
_locManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
//iOS8.0+定位适配
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
// 前台定位授权(默认情况下,不可以在后台获取位置, 勾选后台模式 location update, 但是 会出现蓝条)
[_locManager requestWhenInUseAuthorization];
// 当前的授权状态为前台授权时,此方法也会有效
[_locManager requestAlwaysAuthorization];
}
// 允许后台获取用户位置(iOS9.0)
if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0)
{
// 一定要勾选后台模式 location updates
_locManager.allowsBackgroundLocationUpdates = YES;
}
}
return _locManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
//开始更新用户位置
[self.locManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
/*
更新到位置之后调用
@param manager 位置管理者
@param locations 位置数组
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"定位到了 %@",locations);
//此处locations存储了持续更新的位置坐标值,取最后一个值为最新位置,如果不想让其持续更新位置,
CLLocation *currentLocation = [locations lastObject];
//获取当前所有的城市名
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//根据经纬度反向地理编译出地址信息
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *array, NSError *error)
{
if (array.count > 0)
{
CLPlacemark *placemark = [array objectAtIndex:0];
//NSLog(@%@,placemark.name);//具体位置
//获取城市
NSString *city = placemark.locality;
if (!city) {
//四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
city = placemark.administrativeArea;
}
CLPlacemark *firstPlacemark=[array firstObject];
//经纬度
CLLocationDegrees latitude=firstPlacemark.location.coordinate.latitude;
CLLocationDegrees longitude=firstPlacemark.location.coordinate.longitude;
//打印定位城市
NSLog(@"定位完成:%@",city);
//打印当前经纬度
NSLog(@"%f,%f",latitude,longitude);
//系统会一直更新数据,直到选择停止更新,因为我们只需要获得一次经纬度即可,所以获取之后就停止更新
[manager stopUpdatingLocation];
}else if (error == nil && [array count] == 0)
{
NSLog(@"No results were returned.");
}else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
// 当取得城市位置时候停止更新
[manager stopUpdatingLocation];
}
/*
授权状态发生改变时调用
@param manager 位置管理者
@param status 状态
*/
-(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;
}
default:
break;
}
}
// 定位失败
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"定位失败 %@",error);
}
@end