一、定位介紹
現(xiàn)在很多社交敞贡、電商泵琳、團購應用都引入了地圖和定位功能,似乎地圖功能不再是地圖應用和導航應用所特有的誊役。的確获列,有了地圖和定位功能確實讓我們的生活更加豐富多彩,極大的改變了我們的生活方式蛔垢。要實現(xiàn)地圖击孩、導航功能,往往需要先熟悉定位功能鹏漆。
在iOS中通過CoreLocation框架進行定位操作巩梢。
CoreLocation自身可以單獨使用,和地圖開發(fā)框架MapKit完全是獨立的艺玲,但是往往地圖開發(fā)要配合定位框架使用括蝠。
CoreLocation可以實現(xiàn)的功能:
定位功能
地理編碼與逆地理編碼
二、定位核心類
定位是一個很常用的功能饭聚,如一些地圖軟件打開之后如果用戶允許軟件定位的話忌警,那么打開軟件后就會自動鎖定到當前位置,如果用戶手機移動那么當前位置也會跟隨著變化秒梳。要實現(xiàn)這個功能需要使用CoreLoaction中CLLocationManager類法绵,下面是這個類的使用說明:
1. 類方法:
+ (BOOL)locationServicesEnabled;/* 返回用戶是否啟用定位服務 */
+ (CLAuthorizationStatus)authorizationStatus;/* 定位服務授權狀態(tài),返回枚舉類型 */
typedefNS_ENUM(int,CLAuthorizationStatus){? ?
? ? ? ? ?kCLAuthorizationStatusNotDetermined =0,/* 用戶尚未決定是否啟用定位服務 */
? ? ? ? ?kCLAuthorizationStatusRestricted,/* 沒有獲得用戶授權 */
? ? ? ? ?kCLAuthorizationStatusDenied,/* 用戶禁止使用定位或者定位服務處于關閉狀態(tài) */
? ? ? ? ?kCLAuthorizationStatusAuthorizedAlways,/* 前臺酪碘、后臺定位授權 */
? ? ? ? ?kCLAuthorizationStatusAuthorizedWhenInUse,/* 前臺定位授權 */
};
2. 對象屬性:
? 定位精度desiredAccuracy:
? 枚舉類型:?
? 位置信息更新最小距離distanceFilter:
? 浮點數(shù)朋譬,默認為kCLDistanceFilterNone,表示不進行距離限制
3. 對象方法:
#pragmamark - 定位追蹤
-(void)startUpdatingLocation;/* 開始定位追蹤 */
-(void)stopUpdatingLocation;/* 停止定位追蹤 */
#pragmamark - 導航追蹤
-(void)startUpdatingHeading;/* 開始導航方向追蹤 */
-(void)stopUpdatingHeading;/* 停止導航方向追蹤 */
#pragmamark - 區(qū)域定位追蹤
-(void)startMonitoringForRegion:(CLRegion *)region;/* 開始對某個區(qū)域進行定位追蹤 */
-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止對某個區(qū)域進行定位追蹤 */
#pragmamark - 授權請求
-(void)requestWhenInUseAuthorization;/* 請求獲得應用前臺定位授權 */
-(void)requestAlwaysAuthorization;/* 請求獲得應用前后臺定位授權 */
4. 常用代理方法CLLocationManagerDelegate:
/* 位置發(fā)生改變后調(diào)用兴垦,第一次定位也會調(diào)用 */
-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations;
/* 導航方向發(fā)生變化后調(diào)用 */
-(void)locationManager:(CLLocationManager*)managerdidUpdateHeading:(CLHeading*)newHeading;
/* 進入某個區(qū)域后調(diào)用 */
-(void)locationManager:(CLLocationManager*)managerdidEnterRegion:(CLRegion*)region;
/* 走出某個區(qū)域后調(diào)用 */
-(void)locationManager:(CLLocationManager*)managerdidExitRegion:(CLRegion*)region;
/* 當用戶授權狀態(tài)發(fā)生變化時調(diào)用 */
-(void)locationManager:(CLLocationManager*)managerdidChangeAuthorizationStatus:(CLAuthorizationStatus)status;
三徙赢、定位簡單使用
先要在項目導入CoreLocation框架,然后再導入頭文件:
#import<CoreLocation/CoreLocation.h>
iOS版本不同探越,使用也有一些區(qū)別狡赐,主要區(qū)分為:
iOS8.0之前的定位使用
iOS8.0之后的定位使用
1. iOS8.0之前的定位使用:
1.1 前臺定位:
- (void)viewDidLoad{?
? ? ? ? ?[superviewDidLoad];
? ? ? ? ? if(![CLLocationManagerlocationServicesEnabled]) {
? ? ? ? ? NSLog(@"定位服務當前可能尚未打開,請設置打開扶关!");
? ? ? ? ? return;? ?
? ? ? ? ? }?
? ? ? ? ? ? [self ? initLocationManager];
? ? ? ? ? ?//調(diào)用方法,開始更新用戶位置信息
? ? ? ? ? ? [self.locationM startUpdatingLocation];
}
//創(chuàng)建CLLocationManager并啟動定位
- (void)initLocationManager{
? ? ? ? ? ?//創(chuàng)建CLLocationManager對象并設置代理
? ? ? ? ? ? self.locationM = [[CLLocationManageralloc] init];
? ? ? ? ? ? self.locationM.delegate =self;
? ? ? ? ? ? //設置定位精度和位置更新最小距離
? ? ? ? ? ? self.locationM.distanceFilter =100;
? ? ? ? ? ? self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
//在對應的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager*)manager? ? ? didUpdateLocations:(NSArray *)locations{
? ? ? ? ? ?CLLocation*location = [locations firstObject];//取出第一個位置
? ? ? ? ? /*
? ? ? ? ? ? ? ? ? 使用位置前, 務必判斷當前獲取的位置是否有效
? ? ? ? ? ? ? ? ?如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數(shù)據(jù)錯誤, 不可用
? ? ? ? ?*/
? ? ? ? ? ?if(location.horizontalAccuracy <0)
? ? ? ? ? ? ? ? ?return;
? ? ? ? ? CLLocationCoordinate2D ?coordinate = location.coordinate;//位置坐標
? ? ? ? ? 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);
? ? ? ? //如果不需要實時定位阴汇,使用完即使關閉定位服務
? ? ? ? [self.locationM stopUpdatingLocation];?
}
1.定位頻率和定位精度并不是越精確越好数冬,需要視實際情況而定节槐,因為越精確越耗性能搀庶,也就越費電。
2.定位成功后會根據(jù)設置情況頻繁調(diào)用locationManager:didUpdateLocations:方法
3.每個元素一個CLLocation代表地理位置信息铜异,之所以返回數(shù)組是因為有些時候一個位置點可能包含多個位置哥倔。
4.使用完定位服務后,如果不需要實時監(jiān)控應該立即關閉定位服務揍庄,以節(jié)省資源咆蒿。
5.除了提供定位功能,還可以調(diào)用startMonitoringForRegion:方法對指定區(qū)域進行監(jiān)控蚂子。
1.2 后臺定位:
在前臺的基礎上沃测,勾選后臺模式Location updates
2. iOS8之后的定位使用
iOS8開始,需要請求定位授權:
前臺授權:
在Info.plist文件中配置NSLocationWhenInUseUsageDescription為YES
前后臺授權:
在Info.plist文件中配置NSLocationAlwaysUsageDescription為YES
- (void)viewDidLoad{? ?
? ? ? ? ? ? [superviewDidLoad];
? ? ? ? ? ? if(![CLLocationManagerlocationServicesEnabled]) {
? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"定位服務當前可能尚未打開食茎,請設置打開蒂破!");
? ? ? ? ? ? ? ? ? ? ? ? return;? ?
? ? ? ? ? ? ? }? ?
? ? ? ? ? ? ?[self initLocationManager];
? ? ? ? ? ? //如果沒有授權,則請求用戶授權
? ? ? ? ? ? CLAuthorizationStatus ?status = [CLLocationManager ?authorizationStatus];
? ? ? ? ? ? if(status == kCLAuthorizationStatusNotDetermined){
? ? ? ? ? ? //請求前臺定位授權
? ? ? ? ? ? // [self.locationM requestWhenInUseAuthorization];
? ? ? ? ? ? ?//請求前后臺定位授權
? ? ? ? ? ? ? [self.locationM requestAlwaysAuthorization];? ?
? ? ? ? ? ?}
}
//創(chuàng)建CLLocationManager并啟動定位
- (void)initLocationManager{
? ? ? ? ? ?//創(chuàng)建CLLocationManager對象并設置代理
? ? ? ? ? ?self.locationM = [[CLLocationManageralloc] init];
? ? ? ? ? ?self.locationM.delegate =self;
? ? ? ? ? //設置定位精度和位置更新最小距離
? ? ? ? ? self.locationM.distanceFilter =100;
? ? ? ? ? self.locationM.desiredAccuracy = kCLLocationAccuracyBest;
}
// 當用戶授權狀態(tài)發(fā)生變化時調(diào)用
- (void)locationManager:(CLLocationManager*)manager? ? ? ? didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
? ? ? ? ? ? switch(status) {
? ? ? ? ? ? ? ? ? ? ? ? case ? ?kCLAuthorizationStatusNotDetermined://用戶還未決定{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"用戶還未決定");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? case ? ? kCLAuthorizationStatusRestricted://訪問受限{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"訪問受限");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ?case ? ? kCLAuthorizationStatusDenied://定位關閉時或用戶APP授權為永不授權時調(diào)用{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"定位關閉或者用戶未授權");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;? ? ? ?
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? case ? ?kCLAuthorizationStatusAuthorizedAlways://獲取前后臺定位授權{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"獲取前后臺定位授權");? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self.locationM startUpdatingLocation];
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? case ? ? ?kCLAuthorizationStatusAuthorizedWhenInUse://獲得前臺定位授權{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"獲得前臺定位授權");? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self.locationM startUpdatingLocation];
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?
? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? default:break;?
? ? ? ? ? } ? ? ??
}
//在對應的代理方法中獲取位置信息
- (void)locationManager:(CLLocationManager*)manager? ? ? didUpdateLocations:(NSArray *)locations{
? ? ? ? ? ? ?CLLocation*location = [locations firstObject]; ? //取出第一個位置
? ? ? ? ? ?/*
? ? ? ? ? ? ? 使用位置前, 務必判斷當前獲取的位置是否有效
? ? ? ? ? ? ? 如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數(shù)據(jù)錯誤, 不可用
? ? ? ? ?*/
? ? ? ? ? ? if(location.horizontalAccuracy <0)return;
? ? ? ? ? ? CLLocationCoordinate2D ?coordinate = location.coordinate;//位置坐標
? ? ? ? ? ? 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);
? ? ? ? ? ? ?//如果不需要實時定位别渔,使用完即使關閉定位服務
? ? ? ? ? ? ?[self.locationM stopUpdatingLocation];
}
四附迷、地理編碼
定位服務中還包含CLGeocoder類,用于處理地理編碼和逆地理編碼功能哎媚。
地理編碼:根據(jù)給定的位置(通常是地名)確定地理坐標(經(jīng)喇伯、緯度)。
【位置 -> 地理坐標】
逆地理編碼:可以根據(jù)地理坐標(經(jīng)拨与、緯度)確定位置信息(街道稻据、門牌等)。
【地理坐標 -> 位置】
- (void)viewDidLoad {?
? ? ? ? ? ? [superviewDidLoad];
? ? ? ? ? ?self.geocoder = [[CLGeocoderalloc] init];? ?
? ? ? ? ? ? [selfgetCoordinateByAddress:@"北京"];? ?
? ? ? ? ? ?[self ? getAddressByLatitude:39.54longitude:116.28];
}
#pragma mark 根據(jù)地名確定地理坐標
-(void)getCoordinateByAddress:(NSString*)address{
? ? ? ? ? //地理編碼
? ? ? ? ? [self.geocoder geocodeAddressString:address ? completionHandler:^(NSArray*placemarks,NSError*error) {
? ? ? ? ? ?//取得第一個地標截珍,地標中存儲了詳細的地址信息攀甚,注意:一個地名可能搜索出多個地址
? ? ? ? ? ?CLPlacemark*placemark = [placemarks firstObject];
? ? ? ? ? ?CLLocation*location = placemark.location;//位置
? ? ? ? ? ?CLRegion*region = placemark.region;//區(qū)域
? ? ? ? ? ?NSDictionary*addressDic = placemark.addressDictionary;//詳細地址信息字典
? ? ? ? ? ? NSLog(@"位置:%@,區(qū)域:%@,詳細信息:%@",location,region,addressDic);?
? ? ? ? ? ?}];
}
#pragma mark 根據(jù)坐標取得地名
-(void)getAddressByLatitude:(CLLocationDegrees)latitude ? longitude:(CLLocationDegrees)longitude{
? ? ? ? ? ?//反地理編碼
? ? ? ? ? ?CLLocation*location = [[CLLocationalloc] initWithLatitude:latitude ? ? ? longitude:longitude];?
? ? ? ? ? ? [self.geocoder reverseGeocodeLocation:location ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:^(NSArray*placemarks,NSError*error) {
? ? ? ? ? ? CLPlacemark*placemark = [placemarks firstObject];
? ? ? ? ? ? ?NSLog(@"詳細信息:%@",placemark.addressDictionary);? ?
? ? ? ? ? ? }];
}
地標類CLPlacemark還包含以下信息:
NSString*name = placemark.name;//地名
NSString*thoroughfare = placemark.thoroughfare;//街道
NSString*subThoroughfare = placemark.subThoroughfare;//街道相關信息,例如門牌等
NSString*locality = placemark.locality;// 城市
NSString*subLocality = placemark.subLocality;// 城市相關信息岗喉,例如標志性建筑
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;//關聯(lián)的或利益相關的地標