#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController ()<CLLocationManagerDelegate>
/**
iOS8以后, 要定位, 必须使用位置管理器(授权), 使用 Strong 属性, 保证不被释放
*/
@property (nonatomic, strong) CLLocationManager *locationManager;
@end
@implementation ViewController
/**
如果定位方法不走
1. 没有配置 plist 键值
2. 模拟器 bug
3. 没有使用 strong 的属性
*/
- (void)viewDidLoad {
[super viewDidLoad];
//想要使用定位, 必须使用CLLocationManager
//1. 创建位置管理器
self.locationManager = [CLLocationManager new];
//2. 请求用户授权(iOS8以后才有) 同时配置 plist 列表
//用户使用时授权 大部分的应用应该使用此种授权方式
// 判断可以使用宏定义(获取系统版本号) / respondsToSelector
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
/*
2. 请求用户授权 --> 从iOS8开始, 必须在程序中请求用户授权, 除了写代码, 还要配置plist列表的键值
如果要适配iOS7, 一定要加if判断, 因为低版本的SDK没有授权方法
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { }
1. 如果要授权, 从iOS8开始, 必须在程序中请求用户授权, 除了写代码, 还要配置plist列表的键值
2. 授权方式 -->requestWhenInUseAuthorization 当用户使用的使用授权
-->requestAlwaysAuthorization 永久授权方法
3. 一定要记得授权方法和plist列表匹配 (when / always)
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
4. 如果2个方法都写, 会出现2此授权的情况 (第一次会走第一个方法, 第二次会走第二个方法 --> 一般使用1个方法即可
5. 大部分的程序之使用 "使用期间" 这个授权即可. 如果说列表出出现了3个, 说明两个授权方法写了
6. plist的Value 可以不写, 写上是为了提示用户, 当前程序会在哪些地方使用定位. 建议写上, 提高用户打开的几率
)
*/
if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]){
//当用户使用的使用授权 --> 能看见APP界面的时候就是使用期间
[self.mgr requestWhenInUseAuthorization];
//永久授权方法 --> 锁屏 / 退出后台
// [self.mgr requestAlwaysAuthorization];
}
/**
iOS9新特性 --> 临时获取后台定位权限
*/
//allowsBackgroundLocationUpdates 如果实现了此方法, 还需要配置plist列表
//一定注意适配版本, 要加iOS9判断
if ([UIDevice currentDevice].systemVersion.floatValue >= 9.0) {
self.mgr.allowsBackgroundLocationUpdates = YES;
}
//3. 设置代理 --> 获取用户位置
self.mgr.delegate = self;
//4. 调用开始定位方法
[self.mgr startUpdatingLocation];
// 比较两个位置之前的距离
// 北京和西安的距离
// 创建一个位置对象, 最少只需要两个值, 经纬度
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:40 longitude:116];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:34.27 longitude:108.93];
// 比较的是直线距离
CLLocationDistance distance = [location1 distanceFromLocation:location2];
NSLog(@"distance: %f",distance / 1000);
}
#pragma mark 代理方法
/** 当完成位置更新的时候调用 --> 次方法会频繁调用*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
CLLocation *location = locations.lastObject;
//NSLog(@"locations: %@",location);
//5. 停止定位
//[self.mgr stopUpdatingLocation];
**/
//3. 设置代理, 来获取数据
self.locationManager.delegate = self;
//4. 开始定位
[self.locationManager startUpdatingLocation];
/**
为了省电, 所有要对持续定位 app 进行优化
*/
//5. 距离筛选器 (当用户发生一定位置的改变时, 再去调用代理方法, 以此实现省电)
// 值: 多少米 譬如:设置10, 就代表用户位置发生10米以上的偏移时, 才去定位
self.locationManager.distanceFilter = 10;
//6. 设置精确度 (减少为卫星之间的计算, 以此实现省电)
// 定位的方式: GPS 北斗 基站定位 WiFi 定位
// iPhone打开定位: GPS 跟24颗卫星进行通讯
//desired: 期望
//Accurac: 精准度
//iOS9以前默认kCLLocationAccuracyBest
// self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
NSLog(@"self.%zd",self.locationManager.desiredAccuracy);
}
/**
当用户更新位置的时候调用此方法 频繁调用, 非常耗电
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//CLLocation 位置对象 --> 经纬度
//CLLocationCoordinate2D coordinate 经纬度
//CLLocationDegrees latitude 纬度
//CLLocationDegrees longitude 经度
CLLocation *location = locations.firstObject;
NSLog(@"latitude: %f,longitude: %f",location.coordinate.latitude, location.coordinate.longitude);
}
@end
CLLocation
- 包括几个重要的属性:
- coordinate中包含经度、维度两个属性
- 重要的方法distanceFromLocation 计算该点与本点之间的直线距离
//CLLocation : 位置对象, 最核心的就是经纬度
//CLLocationCoordinate2D coordinate : 2D位置坐标 –> 经纬度//CLLocationDegrees latitude; –> 纬度
//CLLocationDegrees longitude; –> 经度