一巴席、定位介紹
現(xiàn)在很多社交历涝、電商、團(tuán)購應(yīng)用都引入了地圖和定位功能情妖,似乎地圖功能不再是地圖應(yīng)用和導(dǎo)航應(yīng)用所特有的睬关。的確,有了地圖和定位功能確實讓我們的生活更加豐富多彩毡证,極大的改變了我們的生活方式电爹。要實現(xiàn)地圖、導(dǎo)航功能料睛,往往需要先熟悉定位功能丐箩。
在iOS中通過CoreLocation
框架進(jìn)行定位操作。
CoreLocation
自身可以單獨使用恤煞,和地圖開發(fā)框架MapKit
完全是獨立的屎勘,但是往往地圖開發(fā)要配合定位框架使用。
CoreLocation
可以實現(xiàn)的功能:
- 定位功能
- 地理編碼與逆地理編碼
二居扒、定位核心類
定位是一個很常用的功能概漱,如一些地圖軟件打開之后如果用戶允許軟件定位的話,那么打開軟件后就會自動鎖定到當(dāng)前位置喜喂,如果用戶手機(jī)移動那么當(dāng)前位置也會跟隨著變化瓤摧。要實現(xiàn)這個功能需要使用CoreLoaction
中CLLocationManager
類竿裂,下面是這個類的使用說明:
1. 類方法:
+ (BOOL)locationServicesEnabled;/* 返回用戶是否啟用定位服務(wù) */
+ (CLAuthorizationStatus)authorizationStatus;/* 定位服務(wù)授權(quán)狀態(tài),返回枚舉類型 */
typedef NS_ENUM(int, CLAuthorizationStatus){
kCLAuthorizationStatusNotDetermined = 0, /* 用戶尚未決定是否啟用定位服務(wù) */
kCLAuthorizationStatusRestricted, /* 沒有獲得用戶授權(quán) */
kCLAuthorizationStatusDenied, /* 用戶禁止使用定位或者定位服務(wù)處于關(guān)閉狀態(tài) */
kCLAuthorizationStatusAuthorizedAlways, /* 前臺照弥、后臺定位授權(quán) */
kCLAuthorizationStatusAuthorizedWhenInUse, /* 前臺定位授權(quán) */
};
2. 對象屬性:
- 定位精度
desiredAccuracy
:
枚舉類型:
- 位置信息更新最小距離
distanceFilter
:
浮點數(shù)腻异,默認(rèn)為kCLDistanceFilterNone
,表示不進(jìn)行距離限制
3. 對象方法:
#pragma mark - 定位追蹤
-(void)startUpdatingLocation;/* 開始定位追蹤 */
-(void)stopUpdatingLocation;/* 停止定位追蹤 */
#pragma mark - 導(dǎo)航追蹤
-(void)startUpdatingHeading;/* 開始導(dǎo)航方向追蹤 */
-(void)stopUpdatingHeading;/* 停止導(dǎo)航方向追蹤 */
#pragma mark - 區(qū)域定位追蹤
-(void)startMonitoringForRegion:(CLRegion *)region;/* 開始對某個區(qū)域進(jìn)行定位追蹤 */
-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止對某個區(qū)域進(jìn)行定位追蹤 */
#pragma mark - 授權(quán)請求
-(void)requestWhenInUseAuthorization;/* 請求獲得應(yīng)用前臺定位授權(quán) */
-(void)requestAlwaysAuthorization;/* 請求獲得應(yīng)用前后臺定位授權(quán) */
4. 常用代理方法CLLocationManagerDelegate
:
/* 位置發(fā)生改變后調(diào)用这揣,第一次定位也會調(diào)用 */
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations;
/* 導(dǎo)航方向發(fā)生變化后調(diào)用 */
-(void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading;
/* 進(jìn)入某個區(qū)域后調(diào)用 */
-(void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region;
/* 走出某個區(qū)域后調(diào)用 */
-(void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region;
/* 當(dāng)用戶授權(quán)狀態(tài)發(fā)生變化時調(diào)用 */
-(void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
三悔常、定位簡單使用
先要在項目導(dǎo)入CoreLocation框架,然后再導(dǎo)入頭文件:
#import <CoreLocation/CoreLocation.h>
iOS版本不同给赞,使用也有一些區(qū)別机打,主要區(qū)分為:
- iOS8.0之前的定位使用
- iOS8.0之后的定位使用
1. iOS8.0之前的定位使用:
1.1 前臺定位:
- (void)viewDidLoad{
[super viewDidLoad];
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服務(wù)當(dāng)前可能尚未打開,請設(shè)置打開片迅!");
return;
}
[self initLocationManager];
//調(diào)用方法,開始更新用戶位置信息
[self.locationM startUpdatingLocation];
}
//創(chuàng)建CLLocationManager并啟動定位
- (void)initLocationManager{
//創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
//設(shè)置定位精度和位置更新最小距離
self.locationM.distanceFilter = 100;
self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
//在對應(yīng)的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation*> *)locations
{
CLLocation *location = [locations firstObject];//取出第一個位置
/*
使用位置前, 務(wù)必判斷當(dāng)前獲取的位置是否有效
如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數(shù)據(jù)錯誤, 不可用
*/
if (location.horizontalAccuracy < 0)
return;
CLLocationCoordinate2D coordinate = location.coordinate;//位置坐標(biāo)
CGFloat longitude = coordinate.longitude;//經(jīng)度
CGFloat latitude = coordinate.latitude;//緯度
CGFloat altitude = location.altitude;//海拔
CGFloat course = location.course;//方向
CGFloat speed = location.speed;//速度
NSLog(@"經(jīng)度:%f,緯度:%f",longitude,latitude);
NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
//如果不需要實時定位姐帚,使用完即使關(guān)閉定位服務(wù)
[self.locationM stopUpdatingLocation];
}
- 定位頻率和定位精度并不是越精確越好,需要視實際情況而定障涯,因為越精確越耗性能罐旗,也就越費電。
- 定位成功后會根據(jù)設(shè)置情況頻繁調(diào)用
locationManager:didUpdateLocations:
方法 - 每個元素一個
CLLocation
代表地理位置信息唯蝶,之所以返回數(shù)組是因為有些時候一個位置點可能包含多個位置九秀。 - 使用完定位服務(wù)后,如果不需要實時監(jiān)控應(yīng)該立即關(guān)閉定位服務(wù)粘我,以節(jié)省資源鼓蜒。
- 除了提供定位功能,還可以調(diào)用
startMonitoringForRegion:
方法對指定區(qū)域進(jìn)行監(jiān)控征字。
1.2 后臺定位:
在前臺的基礎(chǔ)上都弹,勾選后臺模式Location updates
2. iOS8之后的定位使用
iOS8開始,需要請求定位授權(quán):
- 前臺授權(quán):
在Info.plist文件中配置NSLocationWhenInUseUsageDescription
為YES
- 前后臺授權(quán):
在Info.plist文件中配置NSLocationAlwaysUsageDescription
為YES
- (void)viewDidLoad{
[super viewDidLoad];
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"定位服務(wù)當(dāng)前可能尚未打開匙姜,請設(shè)置打開畅厢!");
return;
}
[self initLocationManager];
//如果沒有授權(quán),則請求用戶授權(quán)
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined){
//請求前臺定位授權(quán)
//[self.locationM requestWhenInUseAuthorization];
//請求前后臺定位授權(quán)
[self.locationM requestAlwaysAuthorization];
}
}
//創(chuàng)建CLLocationManager并啟動定位
- (void)initLocationManager{
//創(chuàng)建CLLocationManager對象并設(shè)置代理
self.locationM = [[CLLocationManager alloc] init];
self.locationM.delegate = self;
//設(shè)置定位精度和位置更新最小距離
self.locationM.distanceFilter = 100;
self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
// 當(dāng)用戶授權(quán)狀態(tài)發(fā)生變化時調(diào)用
- (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined://用戶還未決定
{
NSLog(@"用戶還未決定");
break;
}
case kCLAuthorizationStatusRestricted://訪問受限
{
NSLog(@"訪問受限");
break;
}
case kCLAuthorizationStatusDenied://定位關(guān)閉時或用戶APP授權(quán)為永不授權(quán)時調(diào)用
{
NSLog(@"定位關(guān)閉或者用戶未授權(quán)");
break;
}
case kCLAuthorizationStatusAuthorizedAlways://獲取前后臺定位授權(quán)
{
NSLog(@"獲取前后臺定位授權(quán)");
[self.locationM startUpdatingLocation];
break;
}
case kCLAuthorizationStatusAuthorizedWhenInUse://獲得前臺定位授權(quán)
{
NSLog(@"獲得前臺定位授權(quán)");
[self.locationM startUpdatingLocation];
break;
}
default:break;
}
}
//在對應(yīng)的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation*> *)locations
{
CLLocation *location = [locations firstObject];//取出第一個位置
/*
使用位置前, 務(wù)必判斷當(dāng)前獲取的位置是否有效
如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數(shù)據(jù)錯誤, 不可用
*/
if (location.horizontalAccuracy < 0)
return;
CLLocationCoordinate2D coordinate = location.coordinate;//位置坐標(biāo)
CGFloat longitude = coordinate.longitude;//經(jīng)度
CGFloat latitude = coordinate.latitude;//緯度
CGFloat altitude = location.altitude;//海拔
CGFloat course = location.course;//方向
CGFloat speed = location.speed;//速度
NSLog(@"經(jīng)度:%f,緯度:%f",longitude,latitude);
NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);
//如果不需要實時定位氮昧,使用完即使關(guān)閉定位服務(wù)
[self.locationM stopUpdatingLocation];
}
控制臺打印
四框杜、地理編碼
定位服務(wù)中還包含CLGeocoder
類,用于處理地理編碼和逆地理編碼功能袖肥。
- 地理編碼:根據(jù)給定的位置(通常是地名)確定地理坐標(biāo)(經(jīng)咪辱、緯度)。
【位置 -> 地理坐標(biāo)】
- 逆地理編碼:可以根據(jù)地理坐標(biāo)(經(jīng)椎组、緯度)確定位置信息(街道油狂、門牌等)。
【地理坐標(biāo) -> 位置】
- (void)viewDidLoad {
[super viewDidLoad];
self.geocoder = [[CLGeocoder alloc] init];
[self getCoordinateByAddress:@"北京"];
[self getAddressByLatitude:39.54 longitude:116.28];
}
#pragma mark 根據(jù)地名確定地理坐標(biāo)
-(void)getCoordinateByAddress:(NSString *)address{
//地理編碼
[self.geocoder geocodeAddressString:address
completionHandler:^(NSArray *placemarks, NSError *error) {
//取得第一個地標(biāo),地標(biāo)中存儲了詳細(xì)的地址信息专筷,注意:一個地名可能搜索出多個地址
CLPlacemark *placemark = [placemarks firstObject];
CLLocation *location = placemark.location;//位置
CLRegion *region = placemark.region;//區(qū)域
NSDictionary *addressDic = placemark.addressDictionary;//詳細(xì)地址信息字典
NSLog(@"位置:%@,區(qū)域:%@,詳細(xì)信息:%@",location,region,addressDic);
}];
}
#pragma mark 根據(jù)坐標(biāo)取得地名
-(void)getAddressByLatitude:(CLLocationDegrees)latitude
longitude:(CLLocationDegrees)longitude
{
//反地理編碼
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude
longitude:longitude];
[self.geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks firstObject];
NSLog(@"詳細(xì)信息:%@",placemark.addressDictionary);
}];
}
地標(biāo)類CLPlacemark
還包含以下信息:
NSString *name = placemark.name;//地名
NSString *thoroughfare = placemark.thoroughfare;//街道
NSString *subThoroughfare = placemark.subThoroughfare; //街道相關(guān)信息夹供,例如門牌等
NSString *locality = placemark.locality; // 城市
NSString *subLocality = placemark.subLocality; // 城市相關(guān)信息,例如標(biāo)志性建筑
NSString *administrativeArea = placemark.administrativeArea; // 州
NSString *subAdministrativeArea = placemark.subAdministrativeArea; //其他行政區(qū)域信息
NSString *postalCode = placemark.postalCode; //郵編
NSString *ISOcountryCode = placemark.ISOcountryCode; //國家編碼
NSString *country = placemark.country; //國家
NSString *inlandWater = placemark.inlandWater; //水源仁堪、湖泊
NSString *ocean = placemark.ocean; // 海洋
NSArray *areasOfInterest = placemark.areasOfInterest; //關(guān)聯(lián)的或利益相關(guān)的地標(biāo)