由于項(xiàng)目中少部分用到定位導(dǎo)航功能,就學(xué)習(xí)了一下這方面的知識(shí),有自己總結(jié)的,也有從大神那里學(xué)習(xí)到的,有錯(cuò)誤的地方希望有大神可以幫我提出,立即改正,寫(xiě)這篇文章的目的主要是想自己做個(gè)筆記,省的以后再做的時(shí)候耽誤時(shí)間
整體思路:在視圖即將顯示的時(shí)候?qū)嵗疞ocationManger對(duì)象,設(shè)置代理,在代理方法中獲取到用戶的經(jīng)緯度,然后反地理編碼,把經(jīng)緯度轉(zhuǎn)化成文字,賦值給cityStr,設(shè)置導(dǎo)航
模擬器使用時(shí)需手動(dòng)設(shè)置經(jīng)緯度,也有可能設(shè)置好了,運(yùn)行項(xiàng)目也不會(huì)執(zhí)行,所以建議使用真機(jī)測(cè)試
![43568E90-BBCB-4B2E-A73A-15618058F8AD.png](http://upload-images.jianshu.io/upload_images/1707826-67d3ce658f2fe9b7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
CLLocation 常用屬性簡(jiǎn)介
CLLocationDegrees latitude;緯度
CLLocationDegrees longitude;經(jīng)度
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate; 坐標(biāo),只有x.y
@property(readonly, nonatomic) CLLocationDistance altitude;海拔
@property(readonly, nonatomic) CLLocationAccuracy horizontalAccuracy;水平經(jīng)度
@property(readonly, nonatomic) CLLocationAccuracy verticalAccuracy;垂直經(jīng)度
版本支持
判斷版本,如果大于iOS8需要進(jìn)行授權(quán) ,同時(shí)配置plist文件
![Uploading C0002AE7-960C-4E3A-B2A6-F7A30C1DCBAD_053280.png . . .]
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
這兩個(gè)key
CLLocationManagerDelegate 說(shuō)明
//定位更新;從oldLocation到了newLocation;方法過(guò)期,如果實(shí)現(xiàn)了locationManager:didUpdateLocations:,該方法不被調(diào)用
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
//成功獲取定位數(shù)據(jù)后就會(huì)激發(fā)該方法;locations最后一個(gè)為最新的
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations
//成功獲取設(shè)備方向數(shù)據(jù)后就會(huì)激發(fā)該方法
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
//是否顯示方向刻度
-(BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
//區(qū)域監(jiān)聽(tīng)時(shí),進(jìn)入監(jiān)聽(tīng)區(qū)域
-(void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region
//區(qū)域監(jiān)聽(tīng)時(shí),離開(kāi)監(jiān)聽(tīng)區(qū)域
-(void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region
//定位失敗時(shí)
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error;
//監(jiān)聽(tīng)區(qū)域失敗
- (void)locationManager:(CLLocationManager *)manager
monitoringDidFailForRegion:(nullable CLRegion *)region
withError:(NSError *)error
//授權(quán)狀態(tài)發(fā)生改變
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
//已經(jīng)開(kāi)始監(jiān)聽(tīng)區(qū)域
- (void)locationManager:(CLLocationManager *)manager
didStartMonitoringForRegion:(CLRegion *)region
//暫停了定位數(shù)據(jù)獲取
- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
//恢復(fù)了定位數(shù)據(jù)的獲取
- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
//結(jié)束延遲定位更新時(shí)
- (void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(nullable NSError *)error
//計(jì)入觀光區(qū)域
- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit
實(shí)際應(yīng)用(使用系統(tǒng)的導(dǎo)航)
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//1. 創(chuàng)建位置管理器
self.locationManager = [CLLocationManager new];
//2>判斷版本,如果大于iOS8需要進(jìn)行授權(quán) ,同時(shí)配置plist文件
//用戶使用時(shí)授權(quán) 大部分的應(yīng)用應(yīng)該使用此種授權(quán)方式
// 判斷可以使用宏定義(獲取系統(tǒng)版本號(hào)) / respondsToSelector
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
//使用時(shí)授權(quán)
[self.locationManager requestWhenInUseAuthorization];
// 一直授權(quán)
//[locationManager requestAlwaysAuthorization];
}
//3. 設(shè)置代理, 來(lái)獲取數(shù)據(jù)
self.locationManager.delegate = self;
//4. 開(kāi)始定位
// 開(kāi)始定位不要忘記停止定位 //[self.locationManager stopUpdatingLocation]
[self.locationManager startUpdatingLocation];
// 為了實(shí)現(xiàn)省電目的,對(duì)定位進(jìn)行優(yōu)化
//5. 距離篩選器 (當(dāng)用戶發(fā)生一定位置的改變時(shí), 再去調(diào)用代理方法, 以此實(shí)現(xiàn)省電)
// 值: 多少米 譬如:設(shè)置10, 就代表用戶位置發(fā)生10米以上的偏移時(shí), 才去定位
self.locationManager.distanceFilter = 10;
//6. 設(shè)置精確度 (減少為衛(wèi)星之間的計(jì)算, 以此實(shí)現(xiàn)省電)
// 定位的方式: GPS 北斗 基站定位 WiFi 定位
// iPhone打開(kāi)定位: GPS 跟24顆衛(wèi)星進(jìn)行通訊
//desired: 期望
//Accurac: 精準(zhǔn)度
//extern const CLLocationAccuracy kCLLocationAccuracyBest;設(shè)備 使用電池供電時(shí)候询兴,最高的精度
//extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;精度10米
//extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;精度100米
//extern const CLLocationAccuracy kCLLocationAccuracyKilometer;精度1000米
//extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;精度3000米
//kCLLocationAccuracyBestForNavigation 導(dǎo)航情況下最高精度,一般要有外接電源時(shí)才 能使用
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
}
# pragma mark -懶加載 創(chuàng)建CLGeocoder對(duì)象
-(CLGeocoder *)geo
{
if (!_geo)
{
_geo = [[CLGeocoder alloc] init];
}
return _geo;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
//獲取到經(jīng)緯度
CLLocation *location = locations.firstObject;
//3. 調(diào)用方法即可
[self.geo reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
//3.1 防錯(cuò)處理
if (placemarks.count == 0 || error) {
NSLog(@"沒(méi)有數(shù)據(jù)或數(shù)據(jù)解析出錯(cuò)");
return;
}
//3.2 遍歷數(shù)據(jù)
for (CLPlacemark *pm in placemarks) {
//3.3. 獲取城市信息, 如果有城市信息就顯示, 否則可以顯示行政區(qū)域
if (pm.name) {
self.cityStr = pm.name;
}else{
self.cityStr = pm.locality;
}
}
}];
}
//添加一個(gè)按鈕,實(shí)現(xiàn)點(diǎn)擊事件,
-(IBAction)startNavigation:(id)sender
{
[self.geo geocodeAddressString:self.cityStr completionHandler:^(NSArray *placemarks, NSError *error) {
//獲取到起點(diǎn)的MKplaceMark
MKPlacemark *startPlace = [[MKPlacemark alloc] initWithPlacemark:[placemarks firstObject]];
//等待獲取到起點(diǎn)的placemarks之后在獲取終點(diǎn)的placemarks,block回調(diào)延遲問(wèn)題
[self.geo geocodeAddressString:@"北京市朝陽(yáng)區(qū)東四環(huán)四方橋東南角" completionHandler:^(NSArray *placemarks, NSError *error) {
/**
獲取到終點(diǎn)的MKplaceMark,MKPlaceMark 是ClPlaceMark的子類(lèi)。
*/
MKPlacemark *endPlace = [[MKPlacemark alloc] initWithPlacemark:[placemarks firstObject]];
/**
將MKPlaceMark轉(zhuǎn)換成MKMapItem,這樣可以放入到item這個(gè)數(shù)組中
*/
MKMapItem *startItem = [[MKMapItem alloc ] initWithPlacemark:startPlace];
MKMapItem *endItem = [[MKMapItem alloc ] initWithPlacemark:endPlace];
NSArray *item = @[startItem ,endItem];
//建立字典存儲(chǔ)導(dǎo)航的相關(guān)參數(shù)
NSMutableDictionary *md = [NSMutableDictionary dictionary];
md[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;
md[MKLaunchOptionsMapTypeKey] = [NSNumber numberWithInteger:MKMapTypeStandard];
/**
*調(diào)用app自帶導(dǎo)航,需要傳入一個(gè)數(shù)組和一個(gè)字典哄孤,數(shù)組中放入MKMapItem,
字典中放入對(duì)應(yīng)鍵值
MKLaunchOptionsDirectionsModeKey 開(kāi)啟導(dǎo)航模式
MKLaunchOptionsMapTypeKey 地圖模式
MKMapTypeStandard = 0,
MKMapTypeSatellite,
MKMapTypeHybrid
// 導(dǎo)航模式
MKLaunchOptionsDirectionsModeDriving 開(kāi)車(chē);
MKLaunchOptionsDirectionsModeWalking 步行;
*/ #warning 其實(shí)所有的代碼都是為了下面一句話吹截,打開(kāi)系統(tǒng)自帶的高德地圖然后執(zhí)行某些動(dòng)作,launchOptions里面的參數(shù)指定做哪些動(dòng)作
[MKMapItem openMapsWithItems:item launchOptions:md];
}];
}]
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.locationManager stopUpdatingLocation];
}