1

CoreLocation是iOS中一个提供设备位置的框架。通过这个框架可以实现定位处理,获取位置数据。位置数据通常包括经度,纬度,海拔信息等。

iOS8系统下使用定位服务必须在info.plist文件中添加两个变量NSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescription,这两个Key的值,将分别用于描述应用程序始终使用和使用期间使用定位的说明。

NSLocationAlwaysUsageDescription String 应用程序始终使用定位服务

NSLocationWhenInUseUsageDescription String 使用应用程序期间,可以使用定位服务

CLLocationManager属性和方法

属性名 描述
location:CLLocation 位置
desiredAccuracy:CLLocationAccuray 位置精度
func startUpdatingLocation() 开启更新位置
func stopUpdatingLocation() 停止更新位置
func startUpdatingHeading() 开启更新方向
func stopUdatingHeading() 停止更新方向

精度的六种选择

desiredAccuracy属性 描述
let kCLLocationAccuracyBestForNavigation: CLLocationAccuracy 精度最高,一般用于导航
let kCLLocationAccuracyBest: CLLocationAccuracy 精度最佳
let kCLLocationAccuracyNearestTenMeters: CLLocationAccuracy 精确度10米内
let kCLLocationAccuracyHundredMeters: CLLocationAccuracy 精确度100米内
let kCLLocationAccuracyKilometer: CLLocationAccuracy 精确度1000米内
let kCLLocationAccuracyThreeKilometers: CLLocationAccuracy 精确度3000米内

对于管理器启动更新后,更新将不断传递给位置管理器委托,直到更新结束。我们无法直接控制位置管理器更新的频率,但可以用位置管理器的distanceFilter属性进行间接控制。在启动更新前设置属性distanceFilter,它指定设备移动多少米后才将另一个更新发给委托。定位要求的精度越高、属性distanceFilter的值越小,应用程序耗电量就越大。他的单位是米,我们可以直接使用整型数字来设置这个距离.

locationManager.distanceFilter = 200

用户授权

发出授权申请,设备会弹出提示,请求用户允许使用定位服务。代码如下:

locationManager.requestAlwaysAuthorization()

通过didChangeAuthorizationStatus代理方法,可以获取设备是否允许使用定位服务,代码如下

func locationManager(_ manager: CLLocationManager,
 didChangeAuthorizationStatus status: CLAuthorizationStatus){
   if status == .NotDetermined || status == .Denied{
     //允许使用定位服务

     //开始启动定位更新服务
     locationManager.startUpdatingLocation()

     print("开始定位")
   }
 }

startUpdatingLocation方法启动定位管理,如果我们不需要更新定位时,可以通过stopUpdatingLocation方法来关闭定位管理,这样可以节省电量。

locationManager.stopUpdatingLocation()

对于委托类CLLocationManagerDelegate最常用的方法是:

func locationManager(_ manager: CLLocationManager,
           didUpdateLocations locations: [CLLocation])

定位改变时委托执行这个方法,可以得到新位置,旧位置。location数组里会有前后位置的经度纬度坐标值。

func locationManager(_ manager: CLLocationManager,
           didUpdateLocations locations: [CLLocation]){
             var currlocation:CLLocation
             //获取最新坐标
             currlocation = locations.last as! CLLocation
             //获取经度
             currlocation.coordinate.longitude
             //获取纬度
             currlocation.coordinate.latitude
             //获取海拔
             currlocation.altitude
           }

CLLocation对象包含定位点的相关位置数据,主要有经度、纬度、海拔信息、可以通过属性和方法来获取。

CLLocation属性及方法

属性名 功能
var coordinate: CLLocationCoordinate2D { get } 位置的纬度和经度
var altitude: CLLocationDistance { get } 位置海拔
var horizontalAccuracy: CLLocationAccuracy { get } 位置的水平精度
var verticalAccuracy: CLLocationAccuracy { get } 位置垂直精度
var speed: CLLocationSpeed { get } 位置的方向
var course: CLLocationDirection { get } 位置的速度
func distanceFromLocation(_ location: CLLocation) -> CLLocationDistance 两个位置之间的距离

使用`func locationManager(_ manager: CLLocationManager,

         didUpdateHeading newHeading: CLHeading)`可以获取到设备移动的方向。参数`newHeading`是一个CLHeading对象。CLHeading通过一组属性来提供航向读数:

magneticHeadingtrueHeading。这些值的单位为度。类型为CLLocationDirection,即双精度浮点数。这意味着:

如果航向为0.0,则前进方向为北

如果航向为90.0,则前进方向为东

如果航向为180.0,则前进方向为南

如果航向为270.0,则前进方向为西

magneticHeadingtrueHeading分别表示磁性航向,和真实航向。如果位置服务被关闭了,GPS和WIFI就只能获取磁场航向。只有打开位置服务,才能获取真实航向。

需要注意,在使用代理前,需要开启更新方向:

locationManager.startUpdatingHeading()

CLHeading属性

属性名 描述
magneticHeading 位置的磁极方向
trueHeading 位置的真实方向
headingAccuracy 方向经度
timestamp 时间戳
description 获取方向数据

CLError

当定位失败时就会调用委托方法

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
       //错误处理  当地位出错时调用
       if let clerr = CLError(rawValue: error.code){

       }
   }

//CLError  是一个每枚举类型

public enum CLError : Int {

    case LocationUnknown // location is currently unknown, but CL will keep trying  
                         //  目前未知,请努力获取
    case Denied // Access to location or ranging has been denied by the user
                // 获取位置功能被拒绝使用
    case Network // general, network-related error
                //网络错误
    case HeadingFailure // heading could not be determined
                        //获取的位置标题信息,不能确定
    case RegionMonitoringDenied // Location region monitoring has been denied by the user
                                //位置区域已被用户监测
    case RegionMonitoringFailure // A registered region cannot be monitored
                                //监测器不能注册
    case RegionMonitoringSetupDelayed // CL could not immediately initialize region monitoring
                                      //不能初始化检测器
    case RegionMonitoringResponseDelayed // While events for this fence will be delivered, delivery will not occur immediately
    //区域检测器响应延迟
    case GeocodeFoundNoResult // A geocode request yielded no result
    //地理编码无结果
    case GeocodeFoundPartialResult // A geocode request yielded a partial result
    //地理编码请求得到部分结果
    case GeocodeCanceled // A geocode request was cancelled
    //地理编码 请求被取消
    case DeferredFailed // Deferred mode failed
    //推迟模式失败
    case DeferredNotUpdatingLocation // Deferred mode failed because location updates disabled or paused
    //由于位置更新失败或者暂停,推迟模式失败
    case DeferredAccuracyTooLow // Deferred mode not supported for the requested accuracy
    //推迟模式不支持经度要求
    case DeferredDistanceFiltered // Deferred mode does not support distance filters
    //推迟模式无法支持距离滤波器
    case DeferredCanceled // Deferred mode request canceled a previous request
    //推迟模式被取消
    case RangingUnavailable // Ranging cannot be performed
    //无法进行测距
    case RangingFailure // General ranging failure
    //通用测距故障
}

更多代理的方法请看文档。

地理信息反编码

通过Core Location类得到的地位信息都是以经度和纬度等表示的地理信息。一般都需要反编码城一个地址。

这就需要CLGeocoder类来实现地理信息反编码

iOS9新特性 更灵活的后台定位(摘自)

请求后台定位权限:

方法一

// 1. 实例化定位管理器
_locationManager = [[CLLocationManager alloc] init];
// 2. 设置代理
_locationManager.delegate = self;
// 3. 定位精度
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// 4.请求用户权限:
//分为:
//⓵只在前台开启定位
//⓶在后台也可定位,
//注意:建议只请求⓵和⓶中的一个,如果两个权限都需要,只请求⓶即可,
//⓵⓶这样的顺序,将导致bug:第一次启动程序后,系统将只请求⓵的权限,⓶的权限系统不会请求,只会在下一次启动应用时请求⓶


if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {
    //[_locationManager requestWhenInUseAuthorization];//⓵只在前台开启定位
    [_locationManager requestAlwaysAuthorization];//⓶在后台也可定位
}

// 5.iOS9新特性:将允许出现这种场景:同一app中多个location manager:一些只能在前台定位,另一些可在后台定位(并可随时禁止其后台定位)。
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
    _locationManager.allowsBackgroundLocationUpdates = YES;
}

// 6. 更新用户位置
[_locationManager startUpdatingLocation];

对应的 Info.plist 的XML源码是:

<key>NSLocationAlwaysUsageDescription</key>
<string>请求后台定位权限</string>

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

方法二:

在对应 target 的 Capabilities -> Background Modes -> 开启 Location Updates

例子:

typealias CoreLocationdelegate = ViewController

extension CoreLocationdelegate:CLLocationManagerDelegate{
   func configLocation(){
       //1 the location manager
       let locationManager = CLLocationManager()
       //2 setting the desired accuracy
       locationManager.delegate = self
       locationManager.desiredAccuracy = kCLLocationAccuracyBest
       //3 setting the distance filter
       locationManager.distanceFilter = 1000
       //4 getting permission to use location services
       locationManager.requestAlwaysAuthorization()
       //5 starting the location manager


   }


   func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
     //获取设备是否允许使用定位服务
      if status == CLAuthorizationStatus.Denied || status == CLAuthorizationStatus.NotDetermined{
         locationManager.requestAlwaysAuthorization()
      }else{
          //允许使用定位服务的话,开启定位服务更新
          locationManager.startUpdatingLocation()
          //开启方向更新服务
          locationManager.startUpdatingHeading()
      }
   }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
       //获取最新的坐标
       let theLocation = locations.last
       //获取纬度
       let latitude = theLocation?.coordinate.latitude
       //获取经度
       let longitude = theLocation?.coordinate.longitude

       //获取海拔

       let altitude = theLocation?.altitude

   }


   func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
       //错误处理  当地位出错时调用
       if let clerr = CLError(rawValue: error.code){

       }
   }

   func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
       //可以获取设备移动的方向


   }

dowhilenet
654 声望10 粉丝