需要導(dǎo)入<CoreLocation/CoreLocation.h>頭文件
補(bǔ)充說明,導(dǎo)入頭文件后,系統(tǒng)會(huì)自動(dòng)幫助導(dǎo)入CoreLocation框架
操作步驟:
1.創(chuàng)建管理者(CLLocationManager)
2.請(qǐng)求授權(quán) (request) 需要設(shè)置info.plist
3.設(shè)置代理,獲取數(shù)據(jù)(需要強(qiáng)引用)
4.開始定位 (startUpdatingLocation)
5.didUpdateLocations代理方法
1).底層獲取數(shù)據(jù)在子線程,使用時(shí)在主線程,蘋果自動(dòng)幫助開發(fā)者做了線程管理
2).存在延遲,所以位置管理者需要強(qiáng)引用
3).該方法會(huì)持續(xù)的返回位置信息,無論位置是否發(fā)生改變,停止定位:stopUpdatingLocation
- 創(chuàng)建位置管理者 統(tǒng)一管理位置服務(wù)(manager設(shè)置強(qiáng)引用)
//位置管理者
@property (nonatomic, strong) CLLocationManager *mgr;
self.manager = [[CLLocationManager alloc] init];
- 請(qǐng)求授權(quán)
1).WhenInUseAuthorization (前臺(tái))
2).AlwaysAuthorization (前后臺(tái)都可以)
3).后臺(tái)模式/前臺(tái)+臨時(shí)后臺(tái)(配合NSLocationWhenInUseUsageDescription使用)
還需要設(shè)置info.plist 添加
NSLocationWhenInUseUsageDescription 使用時(shí)
NSLocationAlwaysUsageDescription 前后臺(tái)
//requestWhenInUseAuthorization是 IOS 8.0開始支持,如果兼容低版本,先判斷能否響應(yīng)requestWhenInUseAuthorization方法
if ([self.manager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.manager requestWhenInUseAuthorization];
}
前臺(tái):
whenInUse.png
始終(前后臺(tái)):
always.png
臨時(shí)后臺(tái):開啟臨時(shí)后臺(tái)設(shè)置:
background.png
IOS 9以后 后臺(tái)或臨時(shí)后臺(tái)除了要設(shè)置info.plist文件外
都還需要代碼允許后臺(tái)模式,這樣的好處是將不同的需求分離開,可以更省電(不同的位置管理者分開設(shè)置是否允許后臺(tái))
始終:NSLocationAlwaysUsageDescription
臨時(shí):NSLocationWhenInUseUsageDescription
self.manager.allowsBackgroundLocationUpdates = YES;
Authorization.png
- 獲取數(shù)據(jù) 設(shè)置代理 遵循協(xié)議 實(shí)現(xiàn)代理方法
@interface ViewController ()<CLLocationManagerDelegate>
self.manager.delegate = self;
/**
* 當(dāng)已經(jīng)獲取定位信息后調(diào)用,該方法會(huì)持續(xù)返回位置信息(無論位置是否發(fā)生變化)
*
* @param manager 位置管理者
* @param locations 數(shù)組<位置對(duì)象>
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
//CLLocation 位置對(duì)象
CLLocation *location = locations.lastObject;
//打印坐標(biāo)(經(jīng)緯度)
NSLog(@"%f, %f", location.coordinate.latitude, location.coordinate.longitude);
//[manager stopUpdatingLocation];停止定位(一次性定位)
}
- 開始定位
[self.manager startUpdatingLocation];
- 定位操作耗時(shí)耗電,位置不改變的時(shí)候不需要持續(xù)定位,位置改變?cè)匍_啟定位,所以還需要優(yōu)化持續(xù)化定位
距離篩選器 (distanceFilter) 減少不必要的代理回調(diào)
// 距離篩選器(單位: 米) 當(dāng)距離沒有超出設(shè)定范圍內(nèi),就不會(huì)有回調(diào)
self.manager.distanceFilter = 100;
期望精確度 (desiredAccuracy) 減少不必要的能耗(精確度越低,精確度越低,能耗也越少)
/*
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
extern const CLLocationAccuracy kCLLocationAccuracyBest;
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;
extern const CLLocationAccuracy kCLLocationAccuracyKilometer;
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;
*/
// 期望精確度
self.manager.desiredAccuracy = kCLLocationAccuracyBest;
- 無法獲取定位的原因:
1.沒有設(shè)置info.plist
2.mgr設(shè)置強(qiáng)引用
3.模擬器bug 切換同iOS版本的模擬器
- 完整代碼:
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>
@property (nonatomic,strong) CLLocationManager *manager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 創(chuàng)建位置管理者
self.manager = [[CLLocationManager alloc]init];
// 請(qǐng)求授權(quán)
if ([self.manager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[self.manager requestWhenInUseAuthorization];
}
// 設(shè)置代理
self.manager.delegate = self;
// 開啟定位
[self.manager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
CLLocation *location = locations.lastObject;
NSLog(@"%f,%f",location.coordinate.latitude,location.coordinate.longitude);
//[manager stopUpdatingLocation];停止定位(一次性定位)
}
- 計(jì)算兩個(gè)位置間距離(直線距離):
CLLocation *location1 = [[CLLocation alloc]initWithLatitude:39.2 longitude:40.2];
CLLocation *location2 = [[CLLocation alloc]initWithLatitude:23.2 longitude:234.2];
CLLocationDistance distance = [location1 distanceFromLocation:location2];
NSLog(@"%f",distance);
- CLLocation 位置對(duì)象屬性說明:
// 經(jīng)緯度
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
// 海拔,高度
@property(readonly, nonatomic) CLLocationDistance altitude;
// 水平精確度 用于描述經(jīng)緯度測(cè)量值和真實(shí)值之間的誤差范圍
@property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;
// 垂直精確度 用于描述高度測(cè)量值和真實(shí)值之間的誤差范圍
@property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;
// 航向
@property(readonly, nonatomic) CLLocationDirection course __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_2_2) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
// 瞬時(shí)速度
@property(readonly, nonatomic) CLLocationSpeed speed __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_2_2) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
// 時(shí)間戳
@property(readonly, nonatomic, copy) NSDate *timestamp;
// 樓層 (iPhone 6 增加了氣壓傳感器,之前只能通過海拔估算)
@property(readonly, nonatomic, copy, nullable) CLFloor *floor __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_8_0);
// 描述
@property (nonatomic, readonly, copy) NSString *description;