iOS CoreLocation框架第一章—— CLLocationManager的使用

一、重要属性

CLLocationManager还提供了如下类方法来判断当前设备的定位相关服务状态。

Ø + locationServicesEnabled:返回当前定位服务是否可用。

typedef NS_ENUM(int, CLAuthorizationStatus) {
    kCLAuthorizationStatusNotDetermined = 0,// 用户从未选择过权限

    kCLAuthorizationStatusRestricted, //1 无法使用定位服务,该状态用户无法改变
 
    kCLAuthorizationStatusDenied,  // 2用户拒绝该应用使用定位服务,或是定位服务总开关处于关闭状态
 
    kCLAuthorizationStatusAuthorizedAlways// 3大致是用户允许该程序无论何时都可以使用地理信息
    
    kCLAuthorizationStatusAuthorizedWhenInUse // 4大致是用户同意程序在可见时使用地理位置


  kCLAuthorizationStatusAuthorized   // 这个值已弃用};


Ø + deferredLocationUpdatesAvailable:返回延迟定位更新是否可用。

Ø + significantLocationChangeMonitoringAvailable:返回重大位置改变监听是否可用。

Ø + headingAvailable:返回该设备是否支持磁力计计算方向。

Ø + isRangingAvailable:返回蓝牙信号范围服务是否可用。这是iOS 7新增的方法。

除此之外,在使用CLLocationManager开始定位之前,还可为该对象设置如下属性。

Ø pausesLocationUpdatesAutomatically:设置iOS设备是否可暂停定位来节省电池的电量。如果该属性设为“YES”,则当iOS设备不再需要定位数据时,iOS设备可以自动暂停定位。

Ø distanceFilter:设置CLLocationManager的自动过滤距离。也就是说,只有当设备在水平方向的位置改变超过该数值(以米为单位)指定的距离时才会生成一次位置改变的信号。

Ø desiredAccuracy:设置定位服务的精度。该属性值支持kCLLocationAccuracyBestForNavigation(导航级的最佳精确度)、kCLLocationAccuracyBest(最佳精确度)、kCLLocationAccuracy NearestTenMeters(10米误差)、kCLLocationAccuracyHundredMeters(百米误差)、kCLLocationAccuracyKilometer(千米误差)、kCLLocationAccuracyThreeKilometers(三千米误差)等常量值。当然,也可直接指定一个浮点数作为定位服务允许的误差。

Ø activityType:设置定位数据的用途。该属性支持CLActivityTypeOther(定位数据作为普通用途)、CLActivityTypeAutomotiveNavigation(定位数据作为车辆导航使用)、CLActivityTypeFitness(定位数据作为步行导航使用)和CLActivityTypeOtherNavigation(定位数据作为其他导航使用)这几个枚举值之一。

 

 

 

------------CLLocation
CLLocation类代表一个位置信息,其中还包括了方向和速度。比如我在长安街188号以5公里/小时的速度往西走。CLLocation具有下面的属性和方法:
@property  CLLocationCoordinate2D coordinate; //以经度和纬度表示的位置信息
@property CLLocationDistance altitude;  //海拔
@property CLLocationAccuracy horizontalAccuracy; //水平精度(如:精确到米)
@property CLLocationAccuracy verticalAccuracy; //垂直精度
@property CLLocationDirection course; //方向
@property CLLocationSpeed speed; //速度
-(NSDate *)timeStamp;
//两个位置之间的距离
-(CLLocationDistance)distanceFromLocation:(CLLocation *)location;


-------------CLLocationManager
CLLocationManager类管理和提供位置服务。它的属性和方法有:
@property CLLocation *location; //位置
@property id<CLLocationManagerDelegate> delegate;
@property CLLocationDistance distanceFilter; //距离过滤,比如:500以内
@property CLlocationAccuracy verticalAccuracy; //垂直精度
-(void) startUpdatingLocation; //开始更新位置(比如:你在往某个地方走)
-(void)stopUpdatingLocation; //停止更新位置
-(void)startUpdatingHeading; //开始更新方向(比如:你改往东走)
-(void)stopUpdatingHeading; //停止更新方向
CLLocationManagerDelegate是一个委托类。你的应用程序需要使用这个委托类。当用户改变位置的时候,CLLocationManager回调的方法是:
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
当用户改变方向的时候,所调用的方法是:
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLLHeading *)newHeading;
当iPhone无法获得当前位置的信息时,所回调的方法是:
-(void)locationManager: (CLLocationManager *)manager didFailLoadWithError:(NSError *)error;


二、详细使用

1.iOS8以前使用CLLocationManager

  • 1.导入头文件 <CoreLocation/CoreLocation.h>
  • 2.创建位置管理者 CLLocationManager , 并添加到属性。
  • 3.设置代理、遵守协议、实现代理方法,在代理方法中获取位置信息
  • 4.调用开始更新位置方法
  • 5.设置 每隔多远定位一次精确度,精确度越高越耗电,定位时间越长

    // 1.设置位置管理者属性
    @property (nonatomic, strong) CLLocationManager *lcManager;
    // 2.判断是否打开了位置服务
    if ([CLLocationManager locationServicesEnabled]) {
      // 创建位置管理者对象
      self.lcManager = [[CLLocationManager alloc] init];
      self.lcManager.delegate = self; // 设置代理
      // 设置定位距离过滤参数 (当本次定位和上次定位之间的距离大于或等于这个值时,调用代理方法)
      self.lcManager.distanceFilter = 100;
      self.lcManager.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度(精度越高越耗电)
      [self.lcManager startUpdatingLocation]; // 开始更新位置
    }
    /** 获取到新的位置信息时调用*/
    -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
      NSLog(@"定位到了");
    }
    /** 不能获取位置信息时调用*/
    -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
      NSLog(@"获取定位失败");
    }
  • 6.请求授权,iOS6之后,苹果开始加强保护用户隐私,在 Info.plist 文件中定义 Key提醒用户,提高用户允许定位的概率。

    Info.plist 设置Key
  • 7.如果要后台定位,需要打开后台模式
    iOS CoreLocation框架第一章—— CLLocationManager的使用_第1张图片
    勾选后台模式

2.iOS8.0之后使用CLLocationManager

  • 1.iOS8之后,苹果又进一步加强了隐私保护,不会主动填出对话框,让用户选择
  • 2.需要实现两个方法(实现其一即可),并且 Info.plist 中设置对应的 key ,才会弹框
1.requestWhenInUseAuthorization
  • 1.当程序当前的授权状态为未决定时,在前台时请求定位服务许可时使用。需要先在 Info.plist 文件中设置一个Key:NSLocationWhenInUseUsageDescription, 如果不设置key,系统会忽略定位请求。

    Info.plist 设置对应的Key
  • 2.当用户授权 when-in-use时,程序在前台时可以启动大部分定位服务。如果想要后台定位,需要开启后台定位模式,但在状态栏会出现蓝条提示用户程序正在进行定位。

    [_lcManager requestWhenInUseAuthorization];
    iOS CoreLocation框架第一章—— CLLocationManager的使用_第2张图片
    请求定位的弹框
iOS CoreLocation框架第一章—— CLLocationManager的使用_第3张图片
后台模式下的 blue bar
2.requestAlwaysAuthorization
  • 1.请求前后台定位服务授权,当授权状态为未决定时请求用户授权。前提是在 Info.plist 文件中包含key NSLocationAlwaysUsageDescription

Info.plist中 设置对应的Key
iOS CoreLocation框架第一章—— CLLocationManager的使用_第4张图片
请求定位的弹框
3.注意
  • 1.iOS8之后,如果想要定位,必须调用 requestWhenInUseAuthorizationrequestAlwaysAuthorization方法。
  • 2.如果两个请求授权的方法都执行了,会出现以下情况
    • 1.when-in-use写在前面,第一次打开程序时请求授权,如果勾选了后台模式,进入后台会出现蓝条提示正在定位。当程序退出,第二次打开程序时Always 会再次请求授权。之后进入后台就不会出现蓝条了(前后台都能定位)。
    • 2.Always写在前面, when-in-use写在后面,只会在第一次打开程序时请求授权,因为 Always得到的授权大于when-in-use的到的授权
4.判断是否开启了定位服务
  • 在启动更新位置之前要先判断是否开启了定位服务
    if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
          [self.lcManager startUpdatingLocation]; // 开始更新位置
      }
5.适配版本号的方法
  • when-in-useAlways 都是iOS8之后出现的方法,如果不进行版本适配,运行在iOS7上就会crash,此时需要做版本号判断
  • 1.判断版本号
    if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
    [_lcManager requestAlwaysAuthorization];
    }
  • 2.适配版本的另一种方法
    if ([_lcManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
              [_lcManager requestWhenInUseAuthorization];
          }
6.监听定位服务状态的改变
  • 实现代理方法,判断定位服务的状态
    /** 定位服务状态改变时调用*/
    -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    {
      switch (status) {
          case kCLAuthorizationStatusNotDetermined:
          {
              NSLog(@"用户还未决定授权");
              break;
          }
          case kCLAuthorizationStatusRestricted:
          {
              NSLog(@"访问受限");
              break;
          }
          case kCLAuthorizationStatusDenied:
          {
              // 类方法,判断是否开启定位服务
              if ([CLLocationManager locationServicesEnabled]) {
                  NSLog(@"定位服务开启,被拒绝");
              } else {
                  NSLog(@"定位服务关闭,不可用");
              }
              break;
          }
          case kCLAuthorizationStatusAuthorizedAlways:
          {
              NSLog(@"获得前后台授权");
              break;
          }
          case kCLAuthorizationStatusAuthorizedWhenInUse:
          {
              NSLog(@"获得前台授权");
              break;
          }
          default:
              break;
      }
    }
7.代理方法返回的 locations 信息
  • 当位置管理器,获取到位置后,调用 locationManager:didUpdateLocations:方法,返回的类型为 CLLocation 的位置信息数组,以下为数组包含的属性
    • 1.coordinate : 当前位置的坐标
      • latitude : 纬度
      • longitude : 经度
    • 2.altitude : 海拔,高度
    • 3.horizontalAccuracy : 纬度和经度的精度
    • 4.verticalAccuracy : 垂直精度(获取不到海拔时为负数)
    • 5.course : 行进方向(真北)
    • 6.speed : 以米/秒为单位的速度
    • 7.description : 位置描述信息
      -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *location = [locations firstObject];
      NSLog(@"%@", location);
      }

3.iOS9.0之后使用CLLocationManager

  • 1.iOS9.0之后有一种新的请求定位的方法 requestLocation
  • 2.作用:按照定位精确度从低到高进行排序,逐个进行定位。如果获取到的位置不是精确度最高的那个,也会在定位超时后,通过代理告诉外界。
  • 3.注意:
    • 1.必须实现 ocationManager:didUpdateLocations:locationManager:didFailWithError 方法,但是只调用一次
    • 2.不能与startUpdatingLocation同时使用
      if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
        [self.lcManager requestLocation];
      }
  • 4.实现 requestWhenInUseAuthorizationrequestAlwaysAuthorization 方法,并设置对应的 key

    if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
       // iOS0.0:如果当前的授权状态是使用是授权,那么App退到后台后,将不能获取用户位置,即使勾选后台模式:location
      [_lcManager requestWhenInUseAuthorization];
      }
  • 5.必须勾选后台模式,并设置 allowsBackgroundLocationUpdates 属性为YES(默认是NO)

    • 1.当定位完成时,设置为NO,并且不再定位跟踪
    • 2.使用 -responsdToSelector: 判断

      // iOS9.0+ 要想继续获取位置,需要使用以下属性进行设置(注意勾选后台模式:location)但会出现蓝条
      if ([_lcManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
      _lcManager.allowsBackgroundLocationUpdates = YES;
      }



参考:http://www.jianshu.com/p/ef6994767cbb

你可能感兴趣的:(iOS CoreLocation框架第一章—— CLLocationManager的使用)