前言
在iOS開發中,定位和地圖功能是比較常用的功能之一,要想加入這2大功能,必須基于2個框架進行開發。
(1) CoreLocation:用于地理定位,地理編碼,區域監聽等(著重功能實現)。
(2) MapKit:用于地圖展示,例如大頭針,路線、覆蓋層展示等(著重界面展示)。
這篇文章我們來著重的介紹下CoreLocation框架
簡介
CoreLocaiton框架是百度地圖的定位也是在蘋果API的基礎上進行了封裝。
CoreLocation框架使用前提
導入框架(Xcode5.0之后可以省略)
一 . iOS8.0之前的定位配置
1. 前臺定位
直接引入頭文件設置代理即可
2.后臺定位
?需要在前臺定位基礎上, 勾選后臺模式Location updates
二 . iOS8.0之后的定位配置
1. 前臺定位
請求前臺定位授權, 并在Info.Plist文件中配置Key ( Nslocationwheninuseusagedescription )
參數類型為字符串 如果輸入內容則是提示用戶的內容
2.后臺定位
第一種解決方案
請求前后臺定位授權,并在info.plist文件中配置KEY ( NSLocationAlwaysUsageDescription )
第二種解決方案
需要在前臺定位基礎上, 勾選后臺模式Location updates
導入主頭文件
#import<CoreLocation/CoreLocation.h>
CoreLocation框架使用前須知
CoreLocation框架中所有數據類型的前綴都是CL
CoreLocation中使用CLLocationManager對象來做用戶定位
定位服務
<CLLocationManagerDelegate>需要遵守這個代理
開始更新用戶位置-(void)startUpdatingLocation;
停止更新用戶位置
-(void)stopUpdatingLocation;
當調用了startUpdatingLocation方法后,就開始不斷地請求、刷新用戶的位置,一旦請求到用戶位置就會調用代理的下面方法
-(void)locationManager:(CLLocationManager*)managerdidUpdateLocations:(NSArray*)locations;
locations參數里面裝著CLLocation對象(下面我會詳細介紹CLLocation對象)
為了嚴謹起見,最好在使用定位功能之前判斷當前應用的定位功能是否可用
CLLocationManager有個類方法可以判斷當前應用的定位功能是否可用
+(BOOL)locationServicesEnabled;
@property(assign,nonatomic)CLLocationDistancedistanceFilter;
每隔多少米定位一次
@property(assign,nonatomic)CLLocationAccuracydesiredAccuracy;
定位精確度(越精確就越耗電)
CLLocation對象
CLLocation用來表示某個位置的地理信息,比如經緯度、海拔等等
@property(readonly,nonatomic)CLLocationCoordinate2Dcoordinate;? //經緯度
注:
typedef? struct
{
CLLocationDegreeslatitude;//緯度
CLLocationDegreeslongitude;//經度
} CLLocationCoordinate2D
@property(readonly,nonatomic)CLLocationDistancealtitude; //海拔
@property(readonly,nonatomic)CLLocationDirectioncourse; //路線,航向(取值范圍是0.0°~359.9°,0.0°代表真北方向)
@property(readonly,nonatomic)CLLocationSpeedspeed; //移動速度(單位是m/s)
調用-(CLLocationDistance)distanceFromLocation:(constCLLocation*)location方法可以計算2個位置之間的距離
實例代碼
#import "ViewController.h"#import@interface ViewController ()//位置管理者
@property (nonatomic,strong) CLLocationManager *locManager;
@end
@implementation ViewController
//懶加載
- (CLLocationManager *)locManager{
if (!_locManager) {
//創建位置管理者
_locManager = [[CLLocationManager alloc] init];
//代理
_locManager.delegate = self;
//每隔多少米定位移一次
_locManager.distanceFilter = 3000;
// 精確度越高, 越耗電, 定位時間越長
_locManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
//iOS8.0+定位適配
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
// 前臺定位授權(默認情況下,不可以在后臺獲取位置, 勾選后臺模式 location update, 但是 會出現藍條)
[_locManager requestWhenInUseAuthorization];
// 當前的授權狀態為前臺授權時,此方法也會有效
[_locManager requestAlwaysAuthorization];
}
// 允許后臺獲取用戶位置(iOS9.0)
if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0)
{
// 一定要勾選后臺模式 location updates
_locManager.allowsBackgroundLocationUpdates = YES;
}
}
return _locManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
//開始更新用戶位置
[self.locManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
/*
更新到位置之后調用
@param manager? 位置管理者
@param locations 位置數組
*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"定位到了 %@",locations);
//此處locations存儲了持續更新的位置坐標值,取最后一個值為最新位置,如果不想讓其持續更新位置,
CLLocation *currentLocation = [locations lastObject];
//獲取當前所有的城市名
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//根據經緯度反向地理編譯出地址信息
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *array, NSError *error)
{
if (array.count > 0)
{
CLPlacemark *placemark = [array objectAtIndex:0];
//NSLog(@%@,placemark.name);//具體位置
//獲取城市
NSString *city = placemark.locality;
if (!city) {
//四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city為空,則可知為直轄市)
city = placemark.administrativeArea;
}
CLPlacemark *firstPlacemark=[array firstObject];
//經緯度
CLLocationDegrees latitude=firstPlacemark.location.coordinate.latitude;
CLLocationDegrees longitude=firstPlacemark.location.coordinate.longitude;
//打印定位城市
NSLog(@"定位完成:%@",city);
//打印當前經緯度
NSLog(@"%f,%f",latitude,longitude);
//系統會一直更新數據,直到選擇停止更新,因為我們只需要獲得一次經緯度即可,所以獲取之后就停止更新
[manager stopUpdatingLocation];
}else if (error == nil && [array count] == 0)
{
NSLog(@"No results were returned.");
}else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
// 當取得城市位置時候停止更新
[manager stopUpdatingLocation];
}
/*
授權狀態發生改變時調用
@param manager 位置管理者
@param status 狀態
*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
// 用戶還未決定
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"用戶還未決定");
break;
}
// 問受限
case kCLAuthorizationStatusRestricted:
{
NSLog(@"訪問受限");
break;
}
// 定位關閉時和對此APP授權為never時調用
case kCLAuthorizationStatusDenied:
{
// 定位是否可用(是否支持定位或者定位是否開啟)
if([CLLocationManager locationServicesEnabled])
{
NSLog(@"定位開啟,但被拒");
}else
{
NSLog(@"定位關閉,不可用");
}
// NSLog(@"被拒");
break;
}
// 獲取前后臺定位授權
case kCLAuthorizationStatusAuthorizedAlways:
// case kCLAuthorizationStatusAuthorized: // 失效,不建議使用
{
NSLog(@"獲取前后臺定位授權");
break;
}
// 獲得前臺定位授權
case kCLAuthorizationStatusAuthorizedWhenInUse:
{
NSLog(@"獲得前臺定位授權");
break;
}
default:
break;
}
}
// 定位失敗
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"定位失敗 %@",error);
}
@end