前言:
本章会使用OC和Swift分别进行实现,需要了解Swift的小伙伴可以翻一下之前的博文
LBS和SoloMo(索罗门)
- LBS:基于位置的服务,根据定位展示周边美食、景点等信息(全称:Location Bassed Service)
- SoloMo:将位置社交、本地、移动化(全称:Soclal Local Moblle)
- 社交化:在APP内加入一些社交元素,进行位置分享等
- 本地化:基于LBS周边的搜索等服务
- 移动化:基于3G\4G网络在移动APP上的服务
CoreLocation介绍
- 定位已经可以说是现在APP的主流,没有定位功能的APP都不好意思和大家见面,作为APP的重要组成部分,其实使用也非常简单,本章就苹果的CoreLocation框架进行简单分析和使用
- CoreLocation主要功能
- 地理定位:获取用户所以在区域,得到相应的经纬度或者海拔等一些地理信息
- 地理编码:根据详细的地址转换为经纬度信息
- 反地理编码:根据经纬度信息转换成具体地址
- 区域监听:指定一个区域,当用户进入或者离开这个区域,我们都可以监听到对应信息
- 一般MapKit和一起使用,因为Mapkit就是基于CoreLocation进行开发的,所以MapKit能进行定位也能展示地图,以后会就MapKit进行详解
distanceFilter(距离过滤)和 desiredAccuracy(定位精确度)属性
distanceFilter(距离过滤):最新位置距上次位置之间距离大于这个值,就会告诉通过代理告诉外界
- 默认距离KCLDistanceFilterNone (值为-1,因为小于0,所以会一直打印)
- 单位:米
desiredAccuracy(定位精确度):定位精确度越高,定位时间就越长,也就越耗电
- kCLLocationAccuracyBestForNavigation // 最适合导航
- kCLLocationAccuracyBest // 最好的
- kCLLocationAccuracyNearestTenMeters; // 附近10米
- kCLLocationAccuracyHundredMeters; // 附近100米
- kCLLocationAccuracyKilometer; // 附近1000米
- kCLLocationAccuracyThreeKilometers; // 附近3000米
iOS8之前定位
- 在XCode5之前我们需要用到的框架修需要手动导入(这边使用的是XCode7.3,有冲突的请进行相应调整)
- CoreLocation框架的主头文件#import
// 为了全局只使用一个位置管理者,我们先对CLLocationManager进行懒加载
- (CLLocationManager *)locationM {
if (_locationM == nil) {
// 创建位置管理者
_locationM = [[CLLocationManager alloc] init];
// 设置代理
_locationM.delegate = self;
}
return _locationM;
}
// 在按钮点击事件中开启定位服务
// start:开启服务 stop:关闭服务
// 一旦调用这个方法,就会不断的调用用户信息(因为distanceFilter属性的默认值为-1)
// 基本定位(基于Wifi/GPS)
[self.locationM startUpdatingLocation];
// 这个方法是用来监听重大位置改变(因为基站与基站之间相距大所以这个方法会通过基站进行定位,前提是有电话模块的支持)
// [self.locationM startMonitoringSignificantLocationChanges];
// 先遵守CLLocationManagerDelegate协议,实现下面代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSLog(@"已定位到");
// 定位是非常频繁的,所以获取到用户信息后,最好马上关闭停止定位,以达到省电效果,在适当的时候再重新打开定位
[manager stopUpdatingLocation];
self.locationM = nil;
}
Swift:
// MARK:- 懒加载
private lazy var locationM : CLLocationManager = {
// 创建位置管理者
let locationM = CLLocationManager()
// 设置代理
locationM.delegate = self
return locationM
}()
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// 使用位置管理者获取用户位置信息
// 根据苹果的习惯,一般方法命中带ing(现在进行时),说明一旦执行这个方法,系统就会不断的调用这个方法
// 默认情况下只会在前台进行定位,如果在后台也想要获取用户的位置,需要开启后台模式 location updates
locationM.startUpdatingLocation()
}
// MARK:- CLLocationManagerDelegate
extension ViewController : CLLocationManagerDelegate {
// manager : 位置管理者
// locations : 位置数组
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("已定位到")
// 关闭定位
manager.stopUpdatingLocation()
}
startMonitoringSignificantLocationChanges(重大位置改变监听)
- 当位置发生较大变化后会调用这个服务(基于基站定位,所以必须要有电话模块)
- 优势:当APP被完全关闭后,也可以接收到位置通知,并且让APP进入后台处理,耗电量小
- 劣势:定位精度相对于标准定位服务较低,更新的频率根据当前位置附近的基站密度决定
后台继续定位
如果想要在后台继续进行定位,需要打开后台的定位模式
拓展:
- 标准的定位服务(基于GPS/Wifi/基站的定位服务)
- 程序被完全关闭后就无法再获取位置信息
- 显著位置变化定位服务(基于基站的定位服务,设备必须有电话模块支持)
- 当APP被完全关闭后,也可以接收到位置通知,并且让APP进入后台处理
- 定位精度相对于标准定位服务较低,耗电量小,更新的频率根据当前位置附近的基站密度决定
iOS8之后定位
从iOS8开始,苹果进一步加强了对用户隐私的保护,当APP想范围用户隐私信息的时候,系统不再自动弹出对话框让用户授权,为了能让系统自动弹出用户授权界面,需要进行下面设置
- 解决方案:调用iOS8的API,主动请求用户授权
// 注意:根据官方文档的解释,在使用下面2个方法的时候,如果不在info.plist中配置NSLocationWhenInUseUsageDescription这个key,那么方法都不会生效 // 请求前台定位授权 - (void)requestWhenInUseAuthorization // 注意:根据官方文档的解释,在使用下面2个方法的时候,如果不在info.plist中配置`
- 解决方案:调用iOS8的API,主动请求用户授权