一迷殿、簡(jiǎn)介
- 作用:用來表示某個(gè)位置的地理信息蚜印,比如經(jīng)緯度豫喧、海拔等等
- 常用屬性
// 經(jīng)緯度
@property(readonly,nonatomic)CLLocationCoordinate2Dcoordinate;
// 海拔
@property(readonly,nonatomic)CLLocationDistance altitude;
// 路線遭赂,航向(取值范圍是0.0°~359.9°摘符,0.0°代表真北方向,是根據(jù)gps定位,獲取的設(shè)備移動(dòng)方向)
@property(readonly,nonatomic)CLLocationDirection course;
// 移動(dòng)速度(單位是m/s)拷淘,當(dāng)前速度
@property(readonly,nonatomic)CLLocationSpeed speed;
```
- 方法:可以計(jì)算
2個(gè)位置之間的距離
-> 直線// 獲取兩個(gè)位置之間的直線物理距離 - (CLLocationDistance)distanceFromLocation:(constCLLocation*)location
二、基本使用
-
需求:打印當(dāng)前用戶的行走方向,偏離角度以及對(duì)應(yīng)的行走距離,
- 例如:” 北偏東 30度 方向,移動(dòng)了 8 米”
-
注意:
-
實(shí)現(xiàn)步驟:
- 1> 獲取對(duì)應(yīng)的方向偏向(例如”正東””東偏南”)
- 2> 獲取對(duì)應(yīng)的偏離角度(并判斷是否是正方向)
- 3> 計(jì)算行走距離
- 4> 打印信息
-
思路分析:
-
1.確定確定航向
-
- 2.確定偏移角度
-
3.計(jì)算偏移距離
-
4.打又腹隆:
- 實(shí)現(xiàn)代碼:
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#define isIOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)
@interface ViewController ()<CLLocationManagerDelegate>
{
CLLocation *_lastLocation;
}
/** 位置管理者 */
@property (nonatomic, strong) CLLocationManager *locationM;
@end
@implementation ViewController
#pragma mark -懶加載
-(CLLocationManager *)locationM
{
if (!_locationM) {
//1 創(chuàng)建位置管理者
_locationM = [[CLLocationManager alloc] init];
// 1.1 告訴外界位置的方案: 代理, block 通知
_locationM.delegate = self;
// 設(shè)置每隔多遠(yuǎn)定位一次(1次 111km/100m)
// 最新的位置距離上一次位置之間的距離大于100m, 才會(huì)通過代理告訴外界
// _locationM.distanceFilter = 100;
// kCLLocationAccuracyBestForNavigation // 最適合導(dǎo)航
// kCLLocationAccuracyBest; // 最好的
// kCLLocationAccuracyNearestTenMeters; // 附近10米
// kCLLocationAccuracyHundredMeters; // 100米
// kCLLocationAccuracyKilometer; // 1000米
// kCLLocationAccuracyThreeKilometers; // 3000米
// 定位精確度
// 定位精確度越高, 越耗電, 而且, 定位時(shí)間越長(zhǎng)
_locationM.desiredAccuracy = kCLLocationAccuracyBest;
//**-------ios8.0+定位適配---------- */
if(isIOS(8.0))
{
// 請(qǐng)求前臺(tái)定位授權(quán)
// 默認(rèn)情況下, 只能在前臺(tái)獲取用戶位置
// 如果想要獲取后臺(tái)位置, 需要勾選后臺(tái)模式 location updates , 但是會(huì)出現(xiàn)藍(lán)條
[_locationM requestWhenInUseAuthorization];
// 如果在iOS9.0+想要在前臺(tái)授權(quán)模式下, 在后臺(tái)獲取用戶位置, 我們需要額外的設(shè)置以下屬性為YES
if (isIOS(9.0)) {
_locationM.allowsBackgroundLocationUpdates = YES;
}
// 請(qǐng)求前后臺(tái)定位授權(quán)
// 默認(rèn)在前后臺(tái)都可以獲取用戶位置信息, 無論是否勾選后臺(tái)模式locaiton updates, 而且不會(huì)出現(xiàn)藍(lán)條
// 如果當(dāng)前的授權(quán)狀態(tài)!=用戶為選擇狀態(tài), 那么這個(gè)方法不會(huì)有效
// [_locationM requestAlwaysAuthorization];
}
// 其它適配方案
// if([_locationM respondsToSelector:@selector(requestAlwaysAuthorization)])
// {
// [_locationM requestAlwaysAuthorization];
// }
}
return _locationM;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 2. 使用位置管理者, 開始獲取用戶位置
// 開發(fā)經(jīng)驗(yàn): start 開始某個(gè)服務(wù) stop 停止某個(gè)服務(wù)
// 一旦調(diào)用了這個(gè)方法, 那么就會(huì)不斷的獲取用戶位置信息, 然后告訴外界
// 默認(rèn)情況,只能在前臺(tái)獲取用戶位置信息, 如果我們想要在后臺(tái)獲取位置, 必須勾選后臺(tái)模式 location updates
// 標(biāo)準(zhǔn)定位服務(wù)(基于gps/wifi/基站)
[self.locationM startUpdatingLocation];
// 監(jiān)聽重大位置的改變(基于基站進(jìn)行定位 , 要求, 設(shè)備必須有電話模塊)
// [self.locationM startMonitoringSignificantLocationChanges];
// kCLLocationAccuracyBestForNavigation // 最適合導(dǎo)航
// kCLLocationAccuracyBest; // 最好的
// kCLLocationAccuracyNearestTenMeters; // 附近10米
// kCLLocationAccuracyHundredMeters; // 100米
// kCLLocationAccuracyKilometer; // 1000米
// kCLLocationAccuracyThreeKilometers; // 3000米
// 請(qǐng)求一次位置信息
// 注意 不能與startUpdatingLocation 一起使用
if(isIOS(9.0))
{
// [self.locationM requestLocation];
}
}
#pragma mark -CLLocationManagerDelegate
// 當(dāng)獲取到用戶位置信息時(shí)調(diào)用
// manager : 位置管理者
// locations: 位置數(shù)組 按時(shí)間進(jìn)行排序, 如果想要拿到最新的位置, 直接拿最后一個(gè)
// id+泛型 is kind of
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
// coordinate : 經(jīng)緯度坐標(biāo)
// altitude : 海拔
// horizontalAccuracy :水平海拔 如果是負(fù)數(shù), 代表當(dāng)前位置不可用
// course : 航向(0---359.0)
// - distanceFromLocation : 方法來計(jì)算兩個(gè)點(diǎn)之間的物理距離
// 判斷當(dāng)前位置是否可用
CLLocation *location = [locations lastObject];
if(location.horizontalAccuracy < 0)
return;
// 場(chǎng)景演示:打印當(dāng)前用戶的行走方向,偏離角度以及對(duì)應(yīng)的行走距離,
// 例如:” 北偏東 30度 方向,移動(dòng)了 8 米”
// 1. 確定航向
NSString *angleStr;
switch ((int)location.course / 90) {
case 0:
angleStr = @"北偏東";
break;
case 1:
angleStr = @"東偏南";
break;
case 2:
angleStr = @"南偏西";
break;
case 3:
angleStr = @"西偏北";
break;
default:
angleStr = @"掉溝里去了";
break;
}
// 2. 確定偏離角度
NSInteger angle = (int)location.course % 90;
if(angle == 0)
{
angleStr = [angleStr substringToIndex:1];
}
// 確定行走了多少米
double distance = 0;
if (_lastLocation) {
distance = [location distanceFromLocation:_lastLocation];
}
_lastLocation = location;
// 例如:” 北偏東 30度 方向,移動(dòng)了 8 米”
NSString *noticeStr;
if (angle == 0) {
noticeStr = [NSString stringWithFormat:@"正%@方向, 移動(dòng)了%f米", angleStr, distance];
}else
{
noticeStr = [NSString stringWithFormat:@"%@%zd方向, 移動(dòng)了%f米", angleStr, angle, distance];
}
NSLog(@"%@", noticeStr);
// NSLog(@"定位到了--%@", location);
// 一般我們開發(fā)中, 獲取到用戶位置信息之后, 做一些業(yè)務(wù)邏輯操作
// 針對(duì)于定位一次的情況, 可以在定位到之后 停止獲取用戶位置
// [manager stopUpdatingLocation];
}
// 如果授權(quán)狀態(tài)發(fā)生變化時(shí),調(diào)用
// status : 當(dāng)前的授權(quán)狀態(tài)
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用戶未決定");
break;
}
case kCLAuthorizationStatusRestricted:
{
NSLog(@"受限制");
break;
}
case kCLAuthorizationStatusDenied:
{
// 判斷當(dāng)前設(shè)備是否支持定位, 并且定位服務(wù)是否開啟()
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位開啟,被拒絕");
// ios8,0- 需要截圖提醒引導(dǎo)用戶
// iOS8.0+
// NSURL *url = [NSURL URLWithString:]
// if([[UIApplication sharedApplication] openURL:<#(NSURL *)#>])
}else
{
NSLog(@"定位服務(wù)關(guān)閉");
}
break;
}
case kCLAuthorizationStatusAuthorizedAlways:
{
NSLog(@"前后臺(tái)定位授權(quán)");
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"前臺(tái)定位授權(quán)");
break;
}
default:
break;
}
}
// 定位失敗調(diào)用
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"定位失敗");
}
@end
三启涯、應(yīng)用場(chǎng)景
- 導(dǎo)航
- 電商APP,獲取用戶所在城市
- 數(shù)據(jù)采集用戶信息(例如,統(tǒng)計(jì)app使用分布)
- 查找周邊(周邊好友, 周邊商家等等)
四贬堵、經(jīng)驗(yàn)
- ** 為了給用戶省電,你可以這樣做 **
- 1)不需要獲取用戶位置時(shí),一定要關(guān)閉定位服務(wù):
- 2)如果能滿足項(xiàng)目需求,盡可能的使用”監(jiān)聽顯著位置變化”的定位服務(wù)(打車app)
- 3)如果可以,盡可能使用低精度的desiredAccuracy
- 4)如果是數(shù)據(jù)采集,(一般都是周期性的去輪詢用戶位置),在輪詢期間一定要關(guān)閉定位