由于項目需要地圖功能,公司決定使用百度地圖,但是百度地圖也有很多問題,現(xiàn)在總結(jié)一下在百度地圖中遇到的坑,希望給各位看官一點參考,避免走一些彎路.我使用的百度地圖SDK2.9.1.
iOS地圖SDK鏈接,上面的連接是一些注意事項.
(一)關(guān)于定位的一些設(shè)置
//初始化定位服務(wù)
_locService = [[BMKLocationService alloc] init];
//設(shè)置距離過濾器(默認距離是米)
_locService.distanceFilter = 10;
//設(shè)置定位精度
_locService.desiredAccuracy = kCLLocationAccuracyBest;
//開啟定位服務(wù)
[_locService startUserLocationService];
//指定定位:是否允許后臺定位更新穗慕。默認為NO。只在iOS 9.0之后起作用
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9) {
_locService.allowsBackgroundLocationUpdates = YES;
}
//設(shè)置定位的狀態(tài)
_mapView.userTrackingMode = BMKUserTrackingModeNone;
//顯示定位圖層
_mapView.showsUserLocation = YES;
//設(shè)置定位圖層自定義樣式
BMKLocationViewDisplayParam *userlocationStyle = [[BMKLocationViewDisplayParam alloc] init];
//精度圈是否顯示
userlocationStyle.isRotateAngleValid = YES;
//跟隨態(tài)旋轉(zhuǎn)角度是否生效
userlocationStyle.isAccuracyCircleShow = NO;
//定位圖標
userlocationStyle.locationViewImgName = [UIImage imageNamed:@"圖標名稱"];
//更新參樣式信息
[_mapView updateLocationViewWithParam:userlocationStyle];
(二)關(guān)于當(dāng)前定位位置
首先,顯示當(dāng)前位置,百度地圖提供了三種模式:
typedef enum {
BMKUserTrackingModeNone = 0, /// 普通定位模式
BMKUserTrackingModeFollow, /// 定位跟隨模式
BMKUserTrackingModeFollowWithHeading, /// 定位羅盤模式
} BMKUserTrackingMode;
使用下面代碼就能設(shè)置定位狀態(tài):
//設(shè)置定位的狀態(tài)
_mapView.userTrackingMode = BMKUserTrackingModeNone;
普通定位模式?jīng)]有問題,但是如果設(shè)置定位跟隨或定位羅盤模式,運行app,你會發(fā)現(xiàn)定位點確實是對應(yīng)的狀態(tài),但是當(dāng)你拖動地圖的時候,你就會發(fā)現(xiàn)后兩種模式,又變回了普通定位模式.
我問了百度地圖的工程師,他們說這是當(dāng)前的策略...
所以我感覺設(shè)置跟隨模式和羅盤模式?jīng)]有什么卵用...
(三)關(guān)于用戶方向更新后的設(shè)置
如上面(一)所述,定位點可是設(shè)置樣式參數(shù),當(dāng)你自定義了定位圖標后,你會發(fā)現(xiàn)定位圖標確實換為了自己定義的圖標,而且當(dāng)用戶方向更新后妻导,定位圖標是回發(fā)生旋轉(zhuǎn)的,但是當(dāng)你點擊觸摸屏幕后,定位圖標馬上變?yōu)槌跏嫉那闆r,并且用戶方向更新,定位圖標不在發(fā)生變化.
對于這種情況,我想了一個辦法,就是使用系統(tǒng)的定位,在地圖界面添加一個方向的圖標,如下圖:
代碼如下:
- (void)viewDidLoad {
//版本號
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
//主動請求權(quán)限
[self.mgr requestAlwaysAuthorization];
}
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9) {
self.mgr.allowsBackgroundLocationUpdates = YES;
}
//對系統(tǒng)定位進行設(shè)置
self.mgr.delegate = self;
[self.mgr startUpdatingLocation];
//開始監(jiān)聽(開始獲取位置)
[self.mgr startUpdatingHeading];
}
//pragma mark -用戶方向更新后,會調(diào)用此函數(shù)
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
// 將獲取到的角度轉(zhuǎn)為弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 旋轉(zhuǎn)圖片
self.compasspointer.transform = CGAffineTransformMakeRotation(-angle);
}
//pragma mark - 懶加載
- (CLLocationManager *)mgr
{
if (!_mgr) {
_mgr = [[CLLocationManager alloc] init];
}
return _mgr;
}
當(dāng)然如果覺得這種處理不好,可以再想其他解決辦法~
(四)關(guān)于app切換到后臺產(chǎn)生的問題
當(dāng)app切換到后臺再切換回前臺,mapView
可能會產(chǎn)生黑屏的情況,此時只需在AppDelegate.m
中的applicationWillResignActive:(UIApplication *)application
和applicationDidBecomeActive:(UIApplication *)application
添加如下代碼:
- (void)applicationWillResignActive:(UIApplication *)application {
//程序?qū)⒁M入后臺
[BMKMapView willBackGround];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
//程序進入前臺
[BMKMapView didForeGround];
}
(五)關(guān)于BMKLocationServiceDelegate
設(shè)置定位的委托有如下兩種方式:
- 方式1:
- (void)viewDidLoad {
[super viewDidLoad];
_mapView.delegate = self;
_locService.delegate = self;
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
_locService.delegate = nil;
}
- 方式2
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
_locService.delegate = nil;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_locService.delegate = self;
}
上面兩種方式的區(qū)別:
如果在viewDidLoad里寫定位委托的話,加載完mapView后,定位當(dāng)前位置是可以正常顯示,并且可以隨著位置的變化,定位點也隨之發(fā)生變化.如果切換到后臺,然后再切換回mapView界面,定位點還是會變化.但是會產(chǎn)生一個問題,當(dāng)點擊別的tabbar,切換到別的界面后,再切換回mapView界面,定位點就不再隨著位置的變化而發(fā)生變化了.
如果采用方式2的話,就會避免這種問題.
(六)關(guān)于標注與當(dāng)前位置間距離的計算
//設(shè)置標注的經(jīng)緯度坐標
CGFloat latitude = 39.915168;
CGFloat longitude = 116.403875;
anno.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
//計算所選坐標和當(dāng)前位置之間的距離
CLLocationCoordinate2D currentAnno = CLLocationCoordinate2DMake(latitude, longitude);
BMKMapPoint mp1 = BMKMapPointForCoordinate(currentAnno);
BMKMapPoint mp2 = BMKMapPointForCoordinate(userLocation.location.coordinate);
//distance的單位是米
CLLocationDistance distance = BMKMetersBetweenMapPoints(mp1, mp2);
最后,需要說明一下,系統(tǒng)地圖和高德地圖我也用過了,用法和百度地圖非常相似,尤其是高德地圖,更是相似,很多地方都是把前綴換一下就OK了,其他代碼都不用改,但是有個別地方還是有區(qū)別的,比如說百度地圖的paopaoView,高德地圖和百度地圖是不一樣的.