iOS CLLocation对象详解

来源:互联网 发布:好用的气垫 知乎 编辑:程序博客网 时间:2024/06/04 01:33

一、简介

  • 作用:用来表示某个位置的地理信息,比如经纬度、海拔等等
  • 常用属性

    // 经纬度  @property(readonly,nonatomic)CLLocationCoordinate2Dcoordinate;// 海拔@property(readonly,nonatomic)CLLocationDistance altitude;// 路线,航向(取值范围是0.0°~359.9°,0.0°代表真北方向,是根据gps定位,获取的设备移动方向)@property(readonly,nonatomic)CLLocationDirection course;// 移动速度(单位是m/s),当前速度@property(readonly,nonatomic)CLLocationSpeed speed;
  • 方法:可以计算2个位置之间的距离 -> 直线
      // 获取两个位置之间的直线物理距离  - (CLLocationDistance)distanceFromLocation:(constCLLocation*)location

二、基本使用

  • 需求:打印当前用户的行走方向,偏离角度以及对应的行走距离,
    • 例如:” 北偏东 30度 方向,移动了 8 米”
  • 注意:


    1.png
  • 实现步骤:

    • 1> 获取对应的方向偏向(例如”正东””东偏南”)
    • 2> 获取对应的偏离角度(并判断是否是正方向)
    • 3> 计算行走距离
    • 4> 打印信息
  • 思路分析:

    • 1.确定确定航向


      1.1版.png

      1.2.png
    • 2.确定偏移角度


    3.png

    4.png

    5.png

6.png
  • 3.计算偏移距离

    5.png
  • 4.打印:


    6.png
  • 实现代码:

#import "ViewController.h"#import <CoreLocation/CoreLocation.h>#define isIOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)@interface ViewController ()<CLLocationManagerDelegate>{    CLLocation *_lastLocation;}/** 位置管理者 */@property (nonatomic, strong) CLLocationManager *locationM;@end@implementation ViewController#pragma mark -懒加载-(CLLocationManager *)locationM{    if (!_locationM) {              //1 创建位置管理者        _locationM = [[CLLocationManager alloc] init];        // 1.1 告诉外界位置的方案: 代理, block 通知        _locationM.delegate = self;        // 设置每隔多远定位一次(1次  111km/100m)        // 最新的位置距离上一次位置之间的距离大于100m, 才会通过代理告诉外界//        _locationM.distanceFilter = 100;//         kCLLocationAccuracyBestForNavigation // 最适合导航//         kCLLocationAccuracyBest; // 最好的//         kCLLocationAccuracyNearestTenMeters; // 附近10米//         kCLLocationAccuracyHundredMeters; // 100米//         kCLLocationAccuracyKilometer; // 1000米//         kCLLocationAccuracyThreeKilometers; // 3000米        // 定位精确度        // 定位精确度越高, 越耗电, 而且, 定位时间越长        _locationM.desiredAccuracy = kCLLocationAccuracyBest;        //**-------ios8.0+定位适配---------- */        if(isIOS(8.0))        {            // 请求前台定位授权            // 默认情况下, 只能在前台获取用户位置            // 如果想要获取后台位置, 需要勾选后台模式 location updates , 但是会出现蓝条                    [_locationM requestWhenInUseAuthorization];            // 如果在iOS9.0+想要在前台授权模式下, 在后台获取用户位置, 我们需要额外的设置以下属性为YES            if (isIOS(9.0)) {                _locationM.allowsBackgroundLocationUpdates = YES;            }            // 请求前后台定位授权            // 默认在前后台都可以获取用户位置信息, 无论是否勾选后台模式locaiton updates, 而且不会出现蓝条            // 如果当前的授权状态!=用户为选择状态, 那么这个方法不会有效//            [_locationM requestAlwaysAuthorization];        }        // 其它适配方案//        if([_locationM respondsToSelector:@selector(requestAlwaysAuthorization)])//        {//            [_locationM requestAlwaysAuthorization];//        }    }    return _locationM;}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{        // 2. 使用位置管理者, 开始获取用户位置        // 开发经验: start 开始某个服务  stop 停止某个服务    // 一旦调用了这个方法, 那么就会不断的获取用户位置信息, 然后告诉外界    // 默认情况,只能在前台获取用户位置信息, 如果我们想要在后台获取位置, 必须勾选后台模式 location updates    // 标准定位服务(基于gps/wifi/基站)    [self.locationM startUpdatingLocation];    // 监听重大位置的改变(基于基站进行定位 , 要求, 设备必须有电话模块)//    [self.locationM startMonitoringSignificantLocationChanges];    //         kCLLocationAccuracyBestForNavigation // 最适合导航    //         kCLLocationAccuracyBest; // 最好的    //         kCLLocationAccuracyNearestTenMeters; // 附近10米    //         kCLLocationAccuracyHundredMeters; // 100米    //         kCLLocationAccuracyKilometer; // 1000米    //         kCLLocationAccuracyThreeKilometers; // 3000米    // 请求一次位置信息    // 注意 不能与startUpdatingLocation 一起使用    if(isIOS(9.0))    {//        [self.locationM requestLocation];    }}#pragma mark -CLLocationManagerDelegate// 当获取到用户位置信息时调用// manager : 位置管理者// locations: 位置数组 按时间进行排序, 如果想要拿到最新的位置, 直接拿最后一个// id+泛型 is kind of-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{    // coordinate : 经纬度坐标    // altitude : 海拔    // horizontalAccuracy :水平海拔 如果是负数, 代表当前位置不可用    // course : 航向(0---359.0)    // - distanceFromLocation : 方法来计算两个点之间的物理距离    // 判断当前位置是否可用    CLLocation *location = [locations lastObject];    if(location.horizontalAccuracy < 0)        return;    // 场景演示:打印当前用户的行走方向,偏离角度以及对应的行走距离,    // 例如:” 北偏东  30度  方向,移动了 8 米”    // 1. 确定航向    NSString *angleStr;    switch ((int)location.course / 90) {        case 0:            angleStr = @"北偏东";            break;        case 1:            angleStr = @"东偏南";            break;        case 2:            angleStr = @"南偏西";            break;        case 3:            angleStr = @"西偏北";            break;        default:            angleStr = @"掉沟里去了";            break;    }    // 2. 确定偏离角度    NSInteger angle = (int)location.course % 90;    if(angle == 0)    {        angleStr = [angleStr substringToIndex:1];    }    // 确定行走了多少米    double distance = 0;    if (_lastLocation) {        distance = [location distanceFromLocation:_lastLocation];    }    _lastLocation = location;   // 例如:” 北偏东  30度  方向,移动了 8 米”    NSString *noticeStr;    if (angle == 0) {        noticeStr = [NSString stringWithFormat:@"正%@方向, 移动了%f米", angleStr, distance];    }else    {        noticeStr = [NSString stringWithFormat:@"%@%zd方向, 移动了%f米", angleStr, angle, distance];    }    NSLog(@"%@", noticeStr);//    NSLog(@"定位到了--%@", location);    // 一般我们开发中, 获取到用户位置信息之后, 做一些业务逻辑操作    // 针对于定位一次的情况, 可以在定位到之后 停止获取用户位置//    [manager stopUpdatingLocation];}// 如果授权状态发生变化时,调用// status : 当前的授权状态-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{    switch (status) {        case kCLAuthorizationStatusNotDetermined:        {            NSLog(@"用户未决定");             break;        }        case kCLAuthorizationStatusRestricted:        {            NSLog(@"受限制");            break;        }        case kCLAuthorizationStatusDenied:        {            // 判断当前设备是否支持定位, 并且定位服务是否开启()            if([CLLocationManager locationServicesEnabled])            {                NSLog(@"定位开启,被拒绝");                // ios8,0- 需要截图提醒引导用户                // iOS8.0+//                NSURL *url = [NSURL URLWithString:]//                if([[UIApplication sharedApplication] openURL:<#(NSURL *)#>])            }else            {                NSLog(@"定位服务关闭");            }            break;        }        case kCLAuthorizationStatusAuthorizedAlways:        {             NSLog(@"前后台定位授权");            break;        }        case kCLAuthorizationStatusAuthorizedWhenInUse:        {            NSLog(@"前台定位授权");            break;        }        default:            break;    }}// 定位失败调用-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{    NSLog(@"定位失败");}@end

三、应用场景

  • 1) 导航
  • 2) 电商APP,获取用户所在城市
  • 3) 数据采集用户信息(例如,统计app使用分布)
  • 4) 查找周边(周边好友, 周边商家等等)

四、经验

  • 为了给用户省电,你可以这样做
    • 1)不需要获取用户位置时,一定要关闭定位服务:
    • 2)如果能满足项目需求,尽可能的使用”监听显著位置变化”的定位服务(打车app)
    • 3)如果可以,尽可能使用低精度的desiredAccuracy
    • 4)如果是数据采集,(一般都是周期性的去轮询用户位置),在轮询期间一定要关闭定位


作者:iOS_成才录
链接:http://www.jianshu.com/p/1d80b1c0819c
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原创粉丝点击