1 CoreLocation的基础使用
1>iOS7
1.创建CoreLocation的管理者。CoreLocation要强引用
2.实现CLLocationManagerDelegate代理。
3.开始或停止代理
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
@property (nonatomic, strong)CLLocationManager *mrg;
@end
@implementation ViewController
-(CLLocationManager *)mrg
{
if (_mrg == nil) {
//1,创建CoreLocation的管理者
self.mrg = [[CLLocationManager alloc] init];
}
return _mrg;
}
- (void)viewDidLoad {
[super viewDidLoad];
//2,成为CoreLocation的代理
self.mrg.delegate = self;
//3,开始定位
[self.mrg startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"%s",__func__);
//打印位置信息
/*
location.coordinate; 坐标, 包含经纬度
location.altitude; 设备海拔高度 单位是米
location.course; 设置前进方向 0表示北 90东 180南 270西
location.horizontalAccuracy; 水平精准度
location.verticalAccuracy; 垂直精准度
location.timestamp; 定位信息返回的时间
location.speed; 设备移动速度 单位是米/秒, 适用于行车速度而不太适用于不行
*/
CLLocation *location = [locations lastObject];
NSLog(@"%f,%f",location.coordinate.latitude,location.coordinate.longitude);
// 获取到位置信息之后就会调用(调用频率非常高).如果只需要获取一次, 就要在这里设置停止
// [self.mgr stopUpdatingLocation];
}
2>iOS8
iOS7只要开始定位, 系统就会自动要求用户对你的应用程序授权. 但是从iOS8开始, 想要定位必须先"自己""主动"要求用户授权.在iOS8中不仅仅要主动请求授权, 而且必须再info.plist文件中配置一项属性才能弹出授权窗口,value值可以随意写.eg:iOS7也可以添加,但不强制。
Privacy - Location Usage Description(iOS7)
NSLocationWhenInUseDescription,允许在前台获取GPS的描述
NSLocationAlwaysUsageDescription,允许在后台获取GPS的描述
if([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0)
{
NSLog(@"是iOS8");
// 主动要求用户对我们的程序授权, 授权状态改变就会通知代理
[self.mgr requestAlwaysAuthorization]; // 请求前台和后台定位权限
// [self.mgr requestWhenInUseAuthorization]; // 请求前台定位权限
}
//iOS8中需要额外添加在个代理方法
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
/*
用户从未选择过权限
kCLAuthorizationStatusNotDetermined
无法使用定位服务,该状态用户无法改变
kCLAuthorizationStatusRestricted
用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态
kCLAuthorizationStatusDenied
已经授权(废弃)
kCLAuthorizationStatusAuthorized
用户允许该程序无论何时都可以使用地理信息
kCLAuthorizationStatusAuthorizedAlways
用户同意程序在可见时使用地理位置
kCLAuthorizationStatusAuthorizedWhenInUse
*/
if (status == kCLAuthorizationStatusNotDetermined) {
NSLog(@"等待用户授权");
}else if (status == kCLAuthorizationStatusAuthorizedAlways ||
status == kCLAuthorizationStatusAuthorizedWhenInUse)
{
NSLog(@"授权成功");
// 开始定位
[self.mgr startUpdatingLocation];
}else
{
NSLog(@"授权失败");
}
}
2 CoreLocation的常用属性
1.// 设置多久获取一次(单位是米,超出多米就开始调用)
self.mgr.distanceFilter = 500;
2.// 设置获取位置的精确度
/*
kCLLocationAccuracyBestForNavigation 最佳导航
kCLLocationAccuracyBest; 最精准
kCLLocationAccuracyNearestTenMeters; 10米
kCLLocationAccuracyHundredMeters; 百米
kCLLocationAccuracyKilometer; 千米
kCLLocationAccuracyThreeKilometers; 3千米
*/
self.mgr.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
3 CoreLocation的常用功能
1>导航
// 上一次的位置
@property (nonatomic, strong) CLLocation *previousLocation;
// 总路程
@property (nonatomic, assign) CLLocationDistance sumDistance;
// 总时间
@property (nonatomic, assign) NSTimeInterval sumTime;
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// 获取当前的位置
CLLocation *newLocation = [locations lastObject];
if (self.previousLocation != nil) {
// 计算两次的距离(单位时米)
CLLocationDistance distance = [newLocation distanceFromLocation:self.previousLocation];
// 计算两次之间的时间(单位只秒) timestamp 当前获取到为止信息的时间
NSTimeInterval dTime = [newLocation.timestamp timeIntervalSinceDate:self.previousLocation.timestamp];
// 计算速度(米/秒)
CGFloat speed = distance / dTime;
// 累加时间
self.sumTime += dTime;
// 累加距离
self.sumDistance += distance;
// 计算平均速度
CGFloat avgSpeed = self.sumDistance / self.sumTime;
NSLog(@"距离%f 时间%f 速度%f 平均速度%f 总路程 %f 总时间 %f", distance, dTime, speed, avgSpeed, self.sumDistance, self.sumTime);
}
// 纪录上一次的位置
self.previousLocation = newLocation;
}
2>指南针
// 1.添加指南针图片
UIImageView *iv = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"bg_compasspointer"]];
iv.center = CGPointMake(self.view.center.x, self.view.center.y);
[self.view addSubview:iv];
self.compasspointer = iv;
#pragma mark - CLLocationManagerDelegate
// 当获取到用户方向时就会调用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 设备与磁北的相对角度;trueHeading 设置与真北的相对角度
必须和定位一起使用, 一般使用磁北
顺时针 正
逆时针 负数
*/
// 1.将获取到的角度转为弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋转图片 效果不好,建议使用核心动画
self.compasspointer.transform = CGAffineTransformMakeRotation(-angle);
}
3>区域监听
- (void)viewDidLoad {
[super viewDidLoad];
self.mgr.delegate = self;
// 注意:如果是iOS8, 想进行区域检测, 必须自己主动请求获取用户隐私的权限.像CoreLocation的iOS8使用一样,需要在info添加权限,如NSLocationAlwaysUsageDescription
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0 )
{
[self.mgr requestAlwaysAuthorization];
}
// 开始检测用户所在的区域
//1.创建区域
/*CLRegion 有两个子类是专门用于指定区域的
一个可以指定蓝牙的范围CLBeaconRegion/ 一个是可以指定圆形的范围CLCircularRegion
*/
//创建圆形区域, 指定区域中心点的经纬度, 以及半径、标识
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40.058501, 116.304171);
CLCircularRegion *circular = [[CLCircularRegion alloc] initWithCenter:center radius:500 identifier:@"软件园"];
//2.开始监听
[self.mgr startMonitoringForRegion:circular];
}
#pragma mark - CLLocationManagerDelegate
// 进入监听区域时调用
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(@"进入监听区域时调用");
}
// 离开监听区域时调用
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(@"离开监听区域时调用");
}
4>地理编码
这个方法只需要头文件声明#import <CoreLocation/CoreLocation.h>。而与以上方法不同,是不需要实现代理,只需要简单实现编码对象的方法
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.创建地理编码对象
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
// 2.利用地理编码对象编码
// 根据传入的地址获取该地址对应的经纬度信息
[geocoder geocodeAddressString:@"beijing" completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0 || error != nil) {
return ;
}
// placemarks地标数组, 地标数组中存放着地标, 每一个地标包含了该位置的经纬度以及城市/区域/国家代码/邮编等等..。
for (CLPlacemark *placemark in placemarks) {
NSLog(@"name:%@ addressDictionary:%@ latitude:%f longitude:%f",
placemark.name,
placemark.addressDictionary,
placemark.location.coordinate.latitude,
placemark.location.coordinate.longitude);
NSArray *address = placemark.addressDictionary[@"FormattedAddressLines"];
//遍历数组,读取插入字符串
NSMutableString *strM = [NSMutableString string];
for (NSString *str in address) {
[strM appendString:str];
}
NSLog(@"strm:%@",strM);
}
}];
}
5>反地理编码
和地位编码一样,只需要简单导入头文件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.创建地理编码对象
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:23.0f longitude:112.9f];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark *placemark in placemarks) {
NSLog(@"name:%@ \n addressDictionary:%@ \n latitude:%f \n longitude:%f \n locality:%@",
placemark.name, //具体位置
placemark.addressDictionary, //地理位置详细信息
placemark.location.coordinate.latitude, //经度
placemark.location.coordinate.longitude, //纬度
placemark.locality); //城市名字
}
}];
}
4 第三方框架-LocationManager
同样iOS8需要在info添加权限
#import "INTULocationManager.h"
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.创建位置管理者
INTULocationManager *mgr = [INTULocationManager sharedInstance];
// 2.利用位置管理者获取位置
/*
INTULocationAccuracy 精确度,包括更新的位置和时间
timeout 延时时间
status 发送状态
*/
[mgr requestLocationWithDesiredAccuracy:INTULocationAccuracyRoom timeout:5 delayUntilAuthorized:YES block:^(CLLocation *currentLocation, INTULocationAccuracy achievedAccuracy, INTULocationStatus status) {
if (status == INTULocationStatusSuccess) {
NSLog(@"获取位置成功 %f %f", currentLocation.coordinate.latitude , currentLocation.coordinate.longitude);
}else if(status == INTULocationStatusError)
{
NSLog(@"获取失败");
}
}];
}