在我們發(fā)微博,發(fā)表空間內(nèi)容,以及在朋友圈發(fā)表動(dòng)態(tài)的時(shí)候,會(huì)發(fā)現(xiàn)有一個(gè)位置信息的控件。iOS中是如何定位我們的位置信息的呢?基于此寫一個(gè)小Demo,供大家參考使用。
在iOS中,用于定位時(shí)需要我們導(dǎo)入以下框架:
#import <CoreLocation/CoreLocation.h>
該框架中的CLLocationManager
類可以實(shí)時(shí)的獲取我們位置的經(jīng)緯度。CLLocationManager
相當(dāng)于一個(gè)位置管家,常用的屬性和方法有:
(1)每隔多少米定位一次
@property(assign, nonatomic) CLLocationDistance distanceFilter;
(2)定位的精確度
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
(3)定位信息
@property(readonly, nonatomic, copy) CLLocation *location;
(4)開始定位與關(guān)閉定位
- (void)startUpdatingLocation;
- (void)stopUpdatingLocation;
CLLocation
類是用來表示某一位置的經(jīng)緯度,常用屬性有和方法:
(1)經(jīng)緯度
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
(2)海波高度
@property(readonly, nonatomic) CLLocationDistance altitude;
(3)路線,航向 (范圍在 0.0°~359.9°,0° 是正北 方向)
@property(readonly, nonatomic) CLLocationDirection course;
(4)行走速度
@property(readonly, nonatomic) CLLocationSpeed speed;
(5)計(jì)算兩個(gè)位置之間的距離
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location;
其中CLLocationCoordinate2D
是一個(gè)枚舉類型
typedef struct{
CLLocationDegrees latitude;
CLLocationDegrees longitude;
} CLLocationCoordinate2D;
typedef double CLLocationDistance;
<Demo如下:>
- (void)viewDidLoad {
[super viewDidLoad];
// 是否打開定位服務(wù)
if ([CLLocationManager locationServicesEnabled]) {
NSLog(@"開啟定位服務(wù)");
} else {
NSLog(@"沒有開啟定位服務(wù)");
}
// 創(chuàng)建manager
locationManager = [[CLLocationManager alloc] init];
// 設(shè)置代理
locationManager.delegate = self;
if ([[UIDevice currentDevice].systemVersion floatValue] > 8.0) {
/*
kCLAuthorizationStatusNotDetermined = 0, // 用戶還沒決定 要不要授權(quán)
kCLAuthorizationStatusRestricted, // 應(yīng)用程序受限制,沒有授權(quán)
kCLAuthorizationStatusDenied, // 被用戶拒絕授權(quán)
kCLAuthorizationStatusAuthorizedAlways, // 始終
kCLAuthorizationStatusAuthorizedWhenInUse // 使用應(yīng)用程序期間
*/
// 如果程序定位設(shè)置不是 使用應(yīng)用程序期間,則設(shè)置為 使用應(yīng)用程序期間
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) {
[locationManager requestWhenInUseAuthorization];
}
}
// 設(shè)置精確度,精度越高越耗電!
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager startUpdatingLocation];
// 定位頻率,每隔10米定位一次
CLLocationDistance distance = 10.0;
locationManager.distanceFilter = distance;
}
注意:用戶授權(quán)APP訪問定位服務(wù)
1.不允許訪問
2.使用應(yīng)用程序期間
3.后臺(tái)(始終)
iOS8 app想要獲取定位,必須申請授權(quán),在info.plist中添加:
1、NSLocationAlwaysUsageDescription
始終
2、NSLocationWhenInUseUsageDescription
使用應(yīng)用程序期間
< Delegate >:
#pragma mark - CLLocationManagerDelegate
/**
* 實(shí)時(shí)定位,當(dāng)定位到用戶的位置時(shí),就會(huì)調(diào)用
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// locations數(shù)組里邊存放的是CLLocation對象,一個(gè)CLLocation對象就代表著一個(gè)位置
for (CLLocation *newLocation in locations) {
//拿到經(jīng)緯度
CLLocationCoordinate2D coor2D = newLocation.coordinate;
NSLog(@"緯度為:%f, 經(jīng)度為:%f", coor2D.latitude, coor2D.longitude);
//海拔高度
CLLocationDistance altitude = newLocation.altitude;
NSLog(@"高度為:%f", altitude);
//水平精確度, 垂直精確度
CLLocationAccuracy horizontalAcc = newLocation.horizontalAccuracy;
CLLocationAccuracy verticalAcc = newLocation.verticalAccuracy;
NSLog(@"%f, %f", horizontalAcc, verticalAcc);
//北京站 經(jīng)緯度
CLLocation *anyLocation = [[CLLocation alloc] initWithLatitude:39.909843 longitude:116.433015];
CLLocationDistance distance = [newLocation distanceFromLocation:anyLocation];
NSLog(@"當(dāng)前位置到北京站的距離為:%f米", distance);
//位置反編碼(根據(jù)當(dāng)前的經(jīng)緯度獲取具體的位置信息)
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark *placeMark in placemarks) {
NSLog(@"位置:%@", placeMark.name);
NSLog(@"街道:%@", placeMark.thoroughfare);
NSLog(@"子街道:%@", placeMark.subThoroughfare);
NSLog(@"市:%@", placeMark.locality);
NSLog(@"區(qū)\\縣:%@", placeMark.subLocality);
NSLog(@"行政區(qū):%@", placeMark.administrativeArea);
NSLog(@"國家:%@", placeMark.country);
}
}];
//停止定位,定位是一個(gè)很耗能的功能,在不需要時(shí)應(yīng)當(dāng)停止定位
[manager stopUpdatingLocation];
}
}
注意:在調(diào)用
CLLocationManagerDelegate
的時(shí)候,很多人會(huì)出現(xiàn)程序運(yùn)行時(shí),并沒有進(jìn)入到Delegate方法里。
(1)確定在程序第一次運(yùn)行時(shí)彈出的提示框,你是否選擇了允許,如果沒有此時(shí),你應(yīng)當(dāng)去查看你的模擬器設(shè)置->隱私->位置->當(dāng)前程序->是否允許位置信息(建議選中『使用應(yīng)用程序期間』)
(2)方法(1)確認(rèn)過后,還是沒解決,此時(shí)查看你的程序的Supporting Files->info.plist 文件,是否添加了:
NSLocationWhenInUseUsageDescription
或者NSLocationAlwaysUsageDescription
(3)若以上方法都試過了,還是沒有進(jìn)入到Delegate方法里,那么你該檢查一下你的程序了
檢查沒問題?!好吧,下面來看看小編犯的錯(cuò)誤:
#pragma mark - startUpdatingHeading 和 startUpdatingLocation 及其類似啊,別寫錯(cuò)了
// [locationManager startUpdatingHeading];
[locationManager startUpdatingLocation];
如果此時(shí)你發(fā)現(xiàn)錯(cuò)得和小編一樣的話,請下次一定要提防著Xcode的了,因?yàn)槟闵圆涣羯?敲出 startupdat, 然后瀟灑的按下TAB鍵或者回車的時(shí)候,錯(cuò)誤就已經(jīng)產(chǎn)生了,若不一個(gè)字母一個(gè)字母的檢查,你還真找不出問題所在!
- (void)startUpdatingLocation; // 是開始定位
這兩個(gè)方法的作用截然不同
- (void)startUpdatingHeading; // 是更新方向
開發(fā)路上與君共勉,編程一定要嚴(yán)謹(jǐn)