定位CoreLocation

一、定位介紹

現在很多社交、電商、團購應用都引入了地圖和定位功能,似乎地圖功能不再是地圖應用和導航應用所特有的。的確,有了地圖和定位功能確實讓我們的生活更加豐富多彩,極大的改變了我們的生活方式。要實現地圖、導航功能,往往需要先熟悉定位功能

在iOS中通過CoreLocation框架進行定位操作。

CoreLocation自身可以單獨使用,和地圖開發框架MapKit完全是獨立的,但是往往地圖開發要配合定位框架使用。

CoreLocation可以實現的功能:

定位功能

地理編碼與逆地理編碼

二、定位核心類

定位是一個很常用的功能,如一些地圖軟件打開之后如果用戶允許軟件定位的話,那么打開軟件后就會自動鎖定到當前位置,如果用戶手機移動那么當前位置也會跟隨著變化。要實現這個功能需要使用CoreLoaction中CLLocationManager類,下面是這個類的使用說明:

1. 類方法:

+ (BOOL)locationServicesEnabled;/* 返回用戶是否啟用定位服務 */

+ (CLAuthorizationStatus)authorizationStatus;/* 定位服務授權狀態,返回枚舉類型 */

typedefNS_ENUM(int,CLAuthorizationStatus){? ?

? ? ? ? ?kCLAuthorizationStatusNotDetermined =0,/* 用戶尚未決定是否啟用定位服務 */

? ? ? ? ?kCLAuthorizationStatusRestricted,/* 沒有獲得用戶授權 */

? ? ? ? ?kCLAuthorizationStatusDenied,/* 用戶禁止使用定位或者定位服務處于關閉狀態 */

? ? ? ? ?kCLAuthorizationStatusAuthorizedAlways,/* 前臺、后臺定位授權 */

? ? ? ? ?kCLAuthorizationStatusAuthorizedWhenInUse,/* 前臺定位授權 */

};

2. 對象屬性:

? 定位精度desiredAccuracy:

? 枚舉類型:?

? 位置信息更新最小距離distanceFilter:

? 浮點數,默認為kCLDistanceFilterNone,表示不進行距離限制

3. 對象方法:

#pragmamark - 定位追蹤

-(void)startUpdatingLocation;/* 開始定位追蹤 */

-(void)stopUpdatingLocation;/* 停止定位追蹤 */

#pragmamark - 導航追蹤

-(void)startUpdatingHeading;/* 開始導航方向追蹤 */

-(void)stopUpdatingHeading;/* 停止導航方向追蹤 */

#pragmamark - 區域定位追蹤

-(void)startMonitoringForRegion:(CLRegion *)region;/* 開始對某個區域進行定位追蹤 */

-(void)stopMonitoringForRegion:(CLRegion *)region;/* 停止對某個區域進行定位追蹤 */

#pragmamark - 授權請求

-(void)requestWhenInUseAuthorization;/* 請求獲得應用前臺定位授權 */

-(void)requestAlwaysAuthorization;/* 請求獲得應用前后臺定位授權 */

4. 常用代理方法CLLocationManagerDelegate:

/* 位置發生改變后調用,第一次定位也會調用 */

-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations;

/* 導航方向發生變化后調用 */

-(void)locationManager:(CLLocationManager*)managerdidUpdateHeading:(CLHeading*)newHeading;

/* 進入某個區域后調用 */

-(void)locationManager:(CLLocationManager*)managerdidEnterRegion:(CLRegion*)region;

/* 走出某個區域后調用 */

-(void)locationManager:(CLLocationManager*)managerdidExitRegion:(CLRegion*)region;

/* 當用戶授權狀態發生變化時調用 */

-(void)locationManager:(CLLocationManager*)managerdidChangeAuthorizationStatus:(CLAuthorizationStatus)status;

三、定位簡單使用

先要在項目導入CoreLocation框架,然后再導入頭文件:

#import<CoreLocation/CoreLocation.h>

iOS版本不同,使用也有一些區別,主要區分為:

iOS8.0之前的定位使用

iOS8.0之后的定位使用

1. iOS8.0之前的定位使用:

1.1 前臺定位:

- (void)viewDidLoad{?

? ? ? ? ?[superviewDidLoad];

? ? ? ? ? if(![CLLocationManagerlocationServicesEnabled]) {

? ? ? ? ? NSLog(@"定位服務當前可能尚未打開,請設置打開!");

? ? ? ? ? return;? ?

? ? ? ? ? }?

? ? ? ? ? ? [self ? initLocationManager];

? ? ? ? ? ?//調用方法,開始更新用戶位置信息

? ? ? ? ? ? [self.locationM startUpdatingLocation];

}

//創建CLLocationManager并啟動定位

- (void)initLocationManager{

? ? ? ? ? ?//創建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];//取出第一個位置

? ? ? ? ? /*

? ? ? ? ? ? ? ? ? 使用位置前, 務必判斷當前獲取的位置是否有效

? ? ? ? ? ? ? ? ?如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數據錯誤, 不可用

? ? ? ? ?*/

? ? ? ? ? ?if(location.horizontalAccuracy <0)

? ? ? ? ? ? ? ? ?return;

? ? ? ? ? CLLocationCoordinate2D ?coordinate = location.coordinate;//位置坐標

? ? ? ? ? CGFloat ? longitude = coordinate.longitude;//經度

? ? ? ? ? CGFloat ? ?latitude = coordinate.latitude;//緯度

? ? ? ? ?CGFloat ? ?altitude = location.altitude;//海拔

? ? ? ? ?CGFloat ? ?course = location.course;//方向

? ? ? ? ?CGFloat ? ?speed = location.speed;//速度

? ? ? ? ?NSLog(@"經度:%f,緯度:%f",longitude,latitude);

? ? ? ? ?NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);

? ? ? ? //如果不需要實時定位,使用完即使關閉定位服務

? ? ? ? [self.locationM stopUpdatingLocation];?

}

1.定位頻率和定位精度并不是越精確越好,需要視實際情況而定,因為越精確越耗性能,也就越費電。

2.定位成功后會根據設置情況頻繁調用locationManager:didUpdateLocations:方法

3.每個元素一個CLLocation代表地理位置信息,之所以返回數組是因為有些時候一個位置點可能包含多個位置。

4.使用完定位服務后,如果不需要實時監控應該立即關閉定位服務,以節省資源。

5.除了提供定位功能,還可以調用startMonitoringForRegion:方法對指定區域進行監控。

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];? ?

? ? ? ? ? ?}

}

//創建CLLocationManager并啟動定位

- (void)initLocationManager{

? ? ? ? ? ?//創建CLLocationManager對象并設置代理

? ? ? ? ? ?self.locationM = [[CLLocationManageralloc] init];

? ? ? ? ? ?self.locationM.delegate =self;

? ? ? ? ? //設置定位精度和位置更新最小距離

? ? ? ? ? self.locationM.distanceFilter =100;

? ? ? ? ? self.locationM.desiredAccuracy = kCLLocationAccuracyBest;

}

// 當用戶授權狀態發生變化時調用

- (void)locationManager:(CLLocationManager*)manager? ? ? ? didChangeAuthorizationStatus:(CLAuthorizationStatus)status{

? ? ? ? ? ? switch(status) {

? ? ? ? ? ? ? ? ? ? ? ? case ? ?kCLAuthorizationStatusNotDetermined://用戶還未決定{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"用戶還未決定");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? case ? ? kCLAuthorizationStatusRestricted://訪問受限{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"訪問受限");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ?case ? ? kCLAuthorizationStatusDenied://定位關閉時或用戶APP授權為永不授權時調用{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?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]; ? //取出第一個位置

? ? ? ? ? ?/*

? ? ? ? ? ? ? 使用位置前, 務必判斷當前獲取的位置是否有效

? ? ? ? ? ? ? 如果水平精確度小于零, 代表雖然可以獲取位置對象, 但是數據錯誤, 不可用

? ? ? ? ?*/

? ? ? ? ? ? if(location.horizontalAccuracy <0)return;

? ? ? ? ? ? CLLocationCoordinate2D ?coordinate = location.coordinate;//位置坐標

? ? ? ? ? ? CGFloat ?longitude = coordinate.longitude;//經度

? ? ? ? ? ? CGFloat ?latitude = coordinate.latitude;//緯度

? ? ? ? ? ? CGFloat ?altitude = location.altitude;//海拔

? ? ? ? ? ? ?CGFloat ?course = location.course;//方向

? ? ? ? ? ? ?CGFloat ?speed = location.speed;//速度

? ? ? ? ? ? ? NSLog(@"經度:%f,緯度:%f",longitude,latitude);

? ? ? ? ? ? ? NSLog(@"海拔:%f,方向:%f,速度:%f",altitude,course,speed);

? ? ? ? ? ? ?//如果不需要實時定位,使用完即使關閉定位服務

? ? ? ? ? ? ?[self.locationM stopUpdatingLocation];

}

控制臺打印


四、地理編碼

定位服務中還包含CLGeocoder類,用于處理地理編碼和逆地理編碼功能。

地理編碼:根據給定的位置(通常是地名)確定地理坐標(經、緯度)。

【位置 -> 地理坐標】

逆地理編碼:可以根據地理坐標(經、緯度)確定位置信息(街道、門牌等)。

【地理坐標 -> 位置】

- (void)viewDidLoad {?

? ? ? ? ? ? [superviewDidLoad];

? ? ? ? ? ?self.geocoder = [[CLGeocoderalloc] init];? ?

? ? ? ? ? ? [selfgetCoordinateByAddress:@"北京"];? ?

? ? ? ? ? ?[self ? getAddressByLatitude:39.54longitude:116.28];

}

#pragma mark 根據地名確定地理坐標

-(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;//區域

? ? ? ? ? ?NSDictionary*addressDic = placemark.addressDictionary;//詳細地址信息字典

? ? ? ? ? ? NSLog(@"位置:%@,區域:%@,詳細信息:%@",location,region,addressDic);?

? ? ? ? ? ?}];

}

#pragma mark 根據坐標取得地名

-(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;//其他行政區域信息

NSString*postalCode = placemark.postalCode;//郵編

NSString*ISOcountryCode = placemark.ISOcountryCode;//國家編碼

NSString*country = placemark.country;//國家

NSString*inlandWater = placemark.inlandWater;//水源、湖泊

NSString*ocean = placemark.ocean;// 海洋

NSArray*areasOfInterest = placemark.areasOfInterest;//關聯的或利益相關的地標

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容