CoreLocation - iOS定位
使用 CoreLocation 框架定位,基本分为权限获取,位置更新,区域检测,iBeacon,方向检测,地理编码几方面。
demo链接: Location_Demo
iOS的定位支持
GPS卫星定位
其原理就是:利用天上的卫星(24颗工作卫星和数颗备份星)不断地广播信号, 地面的GPS接收设备收到信号后, 通过分析多个卫星信号,就可以计算出地球坐标, GPS保证全球任何一个地方(98%)都可以同时收到至少4个卫星的信号, 从而可以准确确定您的经纬度以及海拔位置(三颗星只能获得经纬度,四颗星还可以获得海拔高度)。GPS定位精度可达10米以内
iOS的GPS定位于单纯的GPS定位不同,它是A-GPS(所谓辅助GPS),首先通过基站定位或WiFi定位获得该设备的大概位置,然后通过将设备的大致位置发发哦远程服务器,由服务器负责进行查询和计算,从而获取当前位置的卫星信息,并通过网络将这些卫星信息反馈给iOS设备,避免了iOS设备直接通过GPS扫面、分析天上的卫星信息。A-GPS优点是定位快,缺点是需要网络,但也只是在初次定位时需要网络,因为一旦卫星信息返回,在有限时间和范围内,这些信息无须改变,之后的GPS定位就不再需要联网,都是直接用这些卫星参数接受信息了。
与基站、WIFI定位相比,GPS定位耗电量最大,速度最慢,但是精度最高。
基站定位
每个手机基站都是一个标识符,iOS设备可以搜集周围所有收到信号的基站和它们的标识符,通过联网发送到苹果云端服务器,再由服务器根据这些基站的位置信息查询并计算出当前位置,然后把该定位信息返回给手机。
WiFi定位
iOS设备通过无线网卡搜集周围所有的WiFi热点,获得它们的MAC地址,然后通过Apple的云端服务器查询该WiFi热点是否已经登记,如果已经登记,即可获取该WiFi热点的位置,最后通过对多个WiFi热点折中计算得到当前位置并返回给iOS设备。精确度大概在几十米范围内。
定位相关API
首先需要获取地理信息权限。定位权限分为 仅在使用应用期间 和 始终允许 ; 获取到权限后,使用 CLLocationManager 类可以开始在其代理方法 didUpdateLocations 中获得CLLocation位置信息。
1 | //CLLocationManager的常用操作 |
1 | //定位设置: |
可以获得的 CLLocation 位置信息包括了:经纬度、位置的精度、海拔高度、海拔高度的精度、速度等信息。
相应的通过CLLocation 可以计算两地之间的直线距离:
1 | // 北京:39.6 116.39 |
后台定位
后台短时间持续定位
可以在 Background Modes 中开启Location Updates选项。这样就可以实现后台定位,但是该方法只能实现后台定位20-30分钟的时间。
后台永久持续定位
设置代码如下:
1 | //allowsBackgroundLocationUpdates 这个属性是 iOS 9.0 新增的属性, |
该方法让系统不能够自行关闭程序的定位功能,保证程序一直处于后台定位中,
定位权限为应用使用期间的时候,程序在后台运行时会在顶部有一条蓝色的信息框
定位权限为始终的时候,就不会有蓝色框了。
关于 pausesLocationUpdatesAutomatically 属性
CLLocationManager.pausesLocationUpdatesAutomatically 设置是否允许自动暂停定位服务,目前Apple的官方文档描述的很模糊,导致Stackoverflow上有很多的讨论:
该选项主要用来节省电量消耗,防止app在进入后台后没有及时停止定位消耗电量,设置为YES后,当iOS判定设备不太可能发生移动的时候(这句话是Apple文档直译,然而并不知道具体怎么判定),会自动暂停掉定位服务以及相关硬件设备
app在后台定位时,一旦符合了Apple的判定,定位服务以及相关硬件设备被暂停了,除非app回到前台,否则不会恢复定位服务(硬件暂停使得iOS无法判定设备移动)
区域监听
区域监听是指,我们通过CLCircularRegion指定一个区域, 然后当用户持握设备进入或者离开指定区域, 我们都能监听到.
1 | //初始化CLLocationManager等…… |
1 | // 进去监听区域后调用 |
1 | //监听某个区域时, 只有进入或者离开这个区域时, 才能回调对应的方法, 是一个进入或者离开的动作 |
ibeacon
iBeacon 是苹果公司2013年9月发布的移动设备用OS(iOS7)上配备的新功能。其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用BLE技术向周围发送自己特有的 ID,接收到该 ID 的应用软件会根据该 ID 采取一些行动。
iOS 中 iBeacon 是基于地理位置的微定位技术,虽然借助手机蓝牙进行接收Majro、Minor,但是他们在开发工程中没有任何关系。
iBeacon使用苹果提供CoreLocation库,然而在 BLE 在开发过程中使用CoreBluetooth库。从上面提供的库来看就很清楚了,特别是在 iOS8.0 之后的时候如果想使用iBeacon,必须让用户点击是否允许XXapp使用地理位置。如果在第一次使用 iOS App 扫描iBeacon的时候没有提示这句话,是不可能接收到iBeacon的信号(除非iOS 8.0之下)。如果是 BLE 则的开发过程中之需要提示用户打开蓝牙,并不要求其他的地理位置任何信息。
就不写代码了……
地理编码与反地理编码
需要获得网络权限
地理编码:根据给定的地名,获得具体的位置信息(比如经纬度、地址的全称等)。
输入上海市闵行区南华街25号的结果:
1 | CLGeocoder *geocoder = [[CLGeocoder alloc] init]; |
反地理编码:根据给定的经纬度,获得具体的位置信息,省市区街道等信息;
解析定位当前的位置的结果:
1 | CLGeocoder *geocoder = [[CLGeocoder alloc] init]; |
1 | CLPlacemark 地标对象详解 |
方向监测 / 指南针
1 | //获取指南针信息 |
方向补充:
Core Location支持两种不同的获取方向相关信息的方式:
当设备处于某个点时(CLHeading),带有磁力计的设备能能够报告其位置信息;此类被称为设备的朝向。
当设备处于移动过程中时(CLLocation.course),通过带有GPS硬件的报告的位置位置信息;此类被称为设备的行动方向。
朝向和行动方向表现出设备不同的信息。设备的朝向真实的反映出了设备在一个点时相对于磁北或者真北的朝向。而设备的行动方向则表现了设备在运动过程中的运动方向其并没有考虑设备的方向。你使用一种还是这两种相结合,完全取决于你的APP;例如:一个导航APP是否要在两者之间切换完全取决于用户的速度,在步行速度时,设备的朝向对于在当前环境下的确认用户方向是用户最为关心的事情;而在一辆车里运动时,行动方向则变得尤为重要。
后台定位补充:
关于 pausesLocationUpdatesAutomatically 属性:
CLLocationManager.pausesLocationUpdatesAutomatically 设置是否允许自动暂停定位服务,目前Apple的官方文档描述的很模糊,导致Stackoverflow上有很多的讨论:
该选项主要用来节省电量消耗,防止app在进入后台后没有及时停止定位消耗电量,设置为YES后,当iOS判定 设备不太可能发生移动的时候 (这句话是Apple文档直译,然而并不知道具体怎么判定),会自动暂停掉定位服务以及相关硬件设备
唤醒:
首先这个方法需要 始终 权限,然后在开启定位调用 startUpdatingLocation 的同时调用 startMonitoringSignificantLocationChanges 方法。
1 | [_locationManager startUpdatingLocation]; |
开启了这个方法之后,当位置发生较明显的变化时同样会触发一个位置更新事件,这个变化距离不依据 distanceFilter 属性值变化,而是固定的 500 米(指与上一次触发此事件时的距离),且每 5 分钟最多触发一次,触发的时候如果 APP 被杀死了,这个事件还会唤醒 APP ,APP 会在用户无感知的情况下重新走正常的启动流程,只是界面上没有任何显示,此时会在 application:didFinishLaunchingWithOptions: 方法中携带 UIApplicationLaunchOptionsLocationKey 这个 key 来表明当前启动是被位置事件唤醒的,请注意判断这个 key 来绕过一些不需要在后台启动时执行的逻辑,或者执行一些你想要在后台启动后执行的逻辑,比如启动位置上报服务。在 APP 重新启动之后需要重新调用 startMonitoringSignificantLocationChanges 以保证 APP 再次被杀之后能被重新唤醒。
由此方法触发的位置更新事件同样会调用正常位置更新服务 startUpdatingLocation 的locationManager:didUpdateLocations: 回调方法,这个更新事件可能是一个最近缓存的位置,也可能是最新位置,而更精确的位置会在几秒钟之后再次回调,所以如果对细微位置差别比较敏感的话,可以通过回调的 CLLocation 对象中的时间戳来过滤。