地图之简单认识相关类及方法
目录
百度地图相关类及方法
1.基础创建及相关使用类
2.发起导航算路(即开始导航)、导航中改变终点重新导航
3.移除和添加地图的标注、移除地图覆盖物(包折线)
4.发起路线规划、路线规划结果
5.画折线(途经点)
6.地图定位图标
7.逆编码
8.引入相关地图文件名和协议高德地图相关类及方法
1.基础创建及相关使用类
2.发起导航算路(即开始导航)、导航中改变终点重新导航
3.移除和添加地图的标注、移除地图覆盖物(包折线)
4.发起路线规划、路线规划结果
5.画折线(起终点-骑行例子)
6.地图定位图标
7.逆编码
8.引入相关地图文件名和协议地图SDK导入工程及plist权限添加
1.百度地图相关类及方法
1.基础创建及相关使用类
创建地图、当前位置对象、定位管理类
//初始化地图
- (void)initMap {
self.mapView = [[BMKMapView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.mapView];
[self.mapView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
self.mapView.delegate = self;
self.mapZoomLevel = 15;//地图缩放级别
[self.mapView setZoomLevel:self.mapZoomLevel];//级别,3-19
self.mapView.overlookEnabled = NO;// 设定地图View能否支持俯仰角
self.mapView.rotateEnabled = NO;//设定地图View能否支持旋转
[self.locationManager startUpdatingLocation];//开始连续定位
[self.locationManager startUpdatingHeading];//开始获取设备朝向(GPS)
self.mapView.showsUserLocation = YES;//设定是否显示定位图层
self.mapView.userTrackingMode = BMKUserTrackingModeHeading;//普通定位模式
//定位图层自定义样式参数
self.param = [[BMKLocationViewDisplayParam alloc] init];
self.param.isAccuracyCircleShow = NO;//是否显示精度圈
self.param.canShowCallOut = NO;//是否显示气泡
self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
[self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
}
//司机当前位置对象
- (BMKUserLocation *)userLocation {
if (!_userLocation) {
//初始化BMKUserLocation类的实例
_userLocation = [[BMKUserLocation alloc] init];
}
return _userLocation;
}
//负责获取定位
- (BMKLocationManager *)locationManager {
if (!_locationManager) {
//初始化BMKLocationManager类的实例
_locationManager = [[BMKLocationManager alloc] init];
//设置定位管理类实例的代理
_locationManager.delegate = self;
//设定定位坐标系类型,默认为 BMKLocationCoordinateTypeGCJ02
_locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL;
//设定定位精度,默认为 kCLLocationAccuracyBest
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//设定定位类型,默认为 CLActivityTypeAutomotiveNavigation
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
//指定定位是否会被系统自动暂停,默认为NO
_locationManager.pausesLocationUpdatesAutomatically = NO;
/**
是否允许后台定位,默认为NO。只在iOS 9.0及之后起作用。
设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
*/
_locationManager.allowsBackgroundLocationUpdates = NO;
/**
指定单次定位超时时间,默认为10s,最小值是2s。注意单次定位请求前设置。
注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)
后开始计算。
*/
_locationManager.locationTimeout = 10;
}
return _locationManager;
}
//路线规划
- (BMKRouteSearch *)routeSearch {
if (!_routeSearch) {
_routeSearch = [[BMKRouteSearch alloc] init];
_routeSearch.delegate = self;
}
return _routeSearch;
}
地图定位代理方法
/**
* @brief 该方法为BMKLocationManager提供设备朝向的回调方法。
* @param manager 提供该定位结果的BMKLocationManager类的实例
* @param heading 设备的朝向结果
*/
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager
didUpdateHeading:(CLHeading * _Nullable)heading;
/**
* @brief 连续定位回调函数。
* @param manager 定位 BMKLocationManager 类。
* @param location 定位结果,参考BMKLocation。
* @param error 错误信息。
*/
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error;
地图代理方法
/**
*地图初始化完毕时会调用此接口
*@param mapView 地图View
*/
- (void)mapViewDidFinishLoading:(BMKMapView *)mapView;
/**
*地图区域改变完成后会调用此接口
*@param mapView 地图View
*@param animated 是否动画
*@param reason 地区区域改变的原因
*/
- (void)mapView:(BMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated reason:(BMKRegionChangeReason)reason;
/**
*根据anntation生成对应的View
*@param mapView 地图View
*@param annotation 指定的标注
*@return 生成的标注View
*/
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation;
/**
*当点击annotation view弹出的泡泡时,调用此接口
*@param mapView 地图View
*@param view 泡泡所属的annotation view
*/
- (void)mapView:(BMKMapView *)mapView annotationViewForBubble:(BMKAnnotationView *)view;
/**
*当选中一个annotation views时,调用此接口
*当BMKAnnotation的title为nil,BMKAnnotationView的canShowCallout为NO时,不显示气泡,点击BMKAnnotationView会回调此接口。
*当气泡已经弹出,点击BMKAnnotationView不会继续回调此接口。
*@param mapView 地图View
*@param view 选中的annotation views
*/
- (void)mapView:(BMKMapView *)mapView didSelectAnnotationView:(BMKAnnotationView *)view;
/**
*点中底图空白处会回调此接口
*@param mapView 地图View
*@param coordinate 空白处坐标点的经纬度
*/
- (void)mapView:(BMKMapView *)mapView onClickedMapBlank:(CLLocationCoordinate2D)coordinate;
viewForAnnotation方法中自定义气泡view可以设置的一些属性
2.发起导航算路(即开始导航)
/**
* 发起算路
*
* @param eMode 算路方式,定义见BNRoutePlanMode
* @param naviNodes 算路节点数组,起点、途经点、终点按顺序排列,节点信息为BNRoutePlanNode结构
* @param naviTime 发起算路时间,用于优化算路结果,可以为nil
* @param delegate 算路委托,用于回调
* @param userInfo 用户需要传入的参数,货车导航算路需要传入BNaviTripTypeKey,值为BN_NaviTypeTruck
*/
- (void)startNaviRoutePlan:(BNRoutePlanMode)eMode
naviNodes:(NSArray*)naviNodes
time:(BNaviCalcRouteTime*)naviTime
delegete:(id<BNNaviRoutePlanDelegate>)delegate
userInfo:(NSDictionary*)userInfo;
导航中改变终点重新导航
/**
* 导航中改变终点
*
* @param endNode 要切换的终点
*/
- (void)resetNaviEndPoint:(BNRoutePlanNode *)endNode;
3.移除和添加地图的标注
[self.mapView removeAnnotations:self.mapView.annotations];//要移除的标注数组
[self.mapView addAnnotations:clusters];//将一组标注添加到当前地图View中
移除地图覆盖物(包折线)
NSArray *allOverlays = self.mapView.overlays;
[self.mapView removeOverlays:allOverlays];
4.发起路线规划
/**
*驾乘路线检索
*异步函数,返回结果在BMKRouteSearchDelegate的onGetDrivingRouteResult通知
*@param drivingRoutePlanOption 驾车检索信息类
*@return 成功返回YES,否则返回NO
*/
- (BOOL)drivingSearch:(BMKDrivingRoutePlanOption *)drivingRoutePlanOption;
/**
*骑行路线检索
*异步函数,返回结果在BMKRouteSearchDelegate的onGetRidingRouteResult通知
*@param ridingRoutePlanOption 骑行检索信息类
*@return 成功返回YES,否则返回NO
*/
- (BOOL)ridingSearch:(BMKRidingRoutePlanOption *)ridingRoutePlanOption;
#para mark -- 举例:
//初始化司机路径规划
- (void)creatPlan:(OrderListModel *)model {
//起点(司机位置)
BMKPlanNode *start = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D coordinate1;
coordinate1.latitude = [LocationManager shareManager].location.coordinate.latitude;
coordinate1.longitude = [LocationManager shareManager].location.coordinate.longitude;
start.pt = coordinate1;
//终点
BMKPlanNode *end = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D coordinate;
coordinate.latitude = model.start_lat;
coordinate.longitude = model.start_lng;
end.pt = model.startLocation.coordinate;
//开车路线规划
BMKDrivingRoutePlanOption * drivingRoutePlanOption= [[BMKDrivingRoutePlanOption alloc] init];
drivingRoutePlanOption.from = start;
drivingRoutePlanOption.to = end;
drivingRoutePlanOption.drivingPolicy = BMK_DRIVING_DIS_FIRST;//传一个想要的规划策略给百度(最短距离,BMK_DRIVING_DIS_FIRST:1;百度默认0为时间最短)
//节点数组
NSMutableArray *nodesArray = [[NSMutableArray alloc]initWithCapacity:1];
BMKPlanNode *startNode = [[BMKPlanNode alloc] init];
startNode.pt = CLLocationCoordinate2DMake(model.start_lat, model.start_lng);
startNode.name = @"fromeTip";
[nodesArray addObject:startNode];
drivingRoutePlanOption.wayPointsArray = nodesArray;
//发起路线规划
BOOL flag = [self.routeSearch drivingSearch:drivingRoutePlanOption];
if (!flag){
[SKToast showWithText:@"驾车路线规划检索发送失败"];
} else {
[SKToast showWithText:@"成功"];
}
}
路线规划结果
/**
*返回驾乘搜索结果
*@param searcher 搜索对象
*@param result 搜索结果,类型为BMKDrivingRouteResult
*@param error 错误号,@see BMKSearchErrorCode
*/
- (void)onGetDrivingRouteResult:(BMKRouteSearch *)searcher result:(BMKDrivingRouteResult *)result errorCode:(BMKSearchErrorCode)error;
/**
*返回骑行搜索结果
*@param searcher 搜索对象
*@param result 搜索结果,类型为BMKRidingRouteResult
*@param error 错误号,@see BMKSearchErrorCode
*/
- (void)onGetRidingRouteResult:(BMKRouteSearch *)searcher result:(BMKRidingRouteResult *)result errorCode:(BMKSearchErrorCode)error;
5.画折线(途经点)
相关链接:
https://www.jianshu.com/p/ce02bc7d9805
https://www.jianshu.com/p/caf2e185462c
//初始化司机路径规划
- (void)creatPlan:(OrderListModel *)model {
//起点(司机位置)
BMKPlanNode* start = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D coordinate1;
coordinate1.latitude = [LocationManager shareManager].location.coordinate.latitude;
coordinate1.longitude = [LocationManager shareManager].location.coordinate.longitude;
start.pt = coordinate1;
BMKPlanNode* end = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D coordinate;
if ([BBXDiaoduSortArrayManager shareManager].openDiaoduArray.count>0) {//智能调度
NSMutableArray *temArray = [NSMutableArray array];
temArray = [BBXDiaoduSortArrayManager shareManager].pickArray;
OrderListModel *lastModel = temArray.lastObject;
end.pt = lastModel.startLocation.coordinate;
//end.pt = diaoduChuEndCoor;
BMKDrivingRoutePlanOption * drivingRoutePlanOption= [[BMKDrivingRoutePlanOption alloc] init];//开车路线规划
drivingRoutePlanOption.from = start;
drivingRoutePlanOption.to = end;
drivingRoutePlanOption.drivingPolicy = BMK_DRIVING_DIS_FIRST;//传一个想要的规划策略给百度(最短距离,BMK_DRIVING_DIS_FIRST:1;百度默认0为时间最短)
//途径点坐标数组
NSMutableArray <BMKPlanNode *> *wayPointsArray = [[NSMutableArray alloc]init];
[temArray enumerateObjectsUsingBlock:^(OrderListModel * _Nonnull listModel, NSUInteger idx, BOOL * _Nonnull stop) {
//数据源中最后一个元素作为终点,不加入途径点数组
if(idx != temArray.count - 1){//&& idx!=0 奔溃
CLLocationCoordinate2D coor;
coor.latitude = listModel.start_lat;
coor.longitude = listModel.start_lng;
BMKPlanNode *after = [[BMKPlanNode alloc]init];
after.pt = coor;
[wayPointsArray addObject:after];
}
}];
drivingRoutePlanOption.wayPointsArray = wayPointsArray;
BOOL flag = [self.routeSearch drivingSearch:drivingRoutePlanOption];
if (!flag){
[SKToast showWithText:@"驾车路线规划检索发送失败"];
} else {
[SKToast showWithText:@"成功"];
}
}
}
//路径规划结果回调方法
#pragma mark -- 路径规划
/**
*返回驾车的路线绘制搜索结果
*@param searcher 搜索对象
*@param result 搜索结果,类型为BMKDrivingRouteResult
*@param error 错误号,@see BMKSearchErrorCode
*/
- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
if (error == BMK_SEARCH_ST_EN_TOO_NEAR) {//起点,终点距离太近
[SKToast showWithText:@"距离太近,无法规划路线"];
} else {
//检索结果正常返回、其他规划错误
if ([searcher isEqual:self.routeSearch]) {
if (self.ailistArray.count>0) {//智能调度
//规划线路
//1.坐标点的个数
__block NSUInteger pointCount = 0;
BMKDrivingRouteLine *routeline = (BMKDrivingRouteLine *)result.routes.firstObject;//获取所有驾车路线中第一条路线
[routeline.steps enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BMKDrivingStep *step = routeline.steps[idx];
pointCount += step.pointsCount;//遍历所有路段统计路段所经过的地理坐标集合内点的个数
}];
//2.指定的直角坐标点数组
BMKMapPoint *points = new BMKMapPoint[pointCount];
__block NSUInteger j = 0;
[routeline.steps enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BMKDrivingStep *step = routeline.steps[idx];
for (NSUInteger i = 0; i < step.pointsCount; i ++) {
points[j].x = step.points[i].x;//将每条路段所经过的地理坐标点赋值
points[j].y = step.points[i].y;
j ++;
}
}];
//3.根据指定直角坐标点生成一段折线
self.polyline = [BMKPolyline polylineWithPoints:points count:pointCount];
[self.mapView addOverlay:self.polyline];
[self mapViewFitPolyline:self.polyline withMapView:self.mapView];//根据polyline设置地图范围
}
}
}
}
//根据polyline设置地图范围
- (void)mapViewFitPolyline:(BMKPolyline *) polyLine withMapView:(BMKMapView *)mapView {
CGFloat leftTopX, leftTopY, rightBottomX, rightBottomY;
if (polyLine.pointCount < 1) {
return;
}
BMKMapPoint pt = polyLine.points[0];
// 左上角顶点
leftTopX = pt.x;
leftTopY = pt.y;
// 右下角顶点
rightBottomX = pt.x;
rightBottomY = pt.y;
for (int i = 1; i < polyLine.pointCount; i++) {
BMKMapPoint pt = polyLine.points[i];
leftTopX = pt.x < leftTopX ? pt.x : leftTopX;
leftTopY = pt.y < leftTopY ? pt.y : leftTopY;
rightBottomX = pt.x > rightBottomX ? pt.x : rightBottomX;
rightBottomY = pt.y > rightBottomY ? pt.y : rightBottomY;
}
BMKMapRect rect;
rect.origin = BMKMapPointMake(leftTopX, leftTopY);
rect.size = BMKMapSizeMake(rightBottomX - leftTopX, rightBottomY - leftTopY);
UIEdgeInsets padding = UIEdgeInsetsMake(100, 100, 100, 100);//这个自己根据需求调整
BMKMapRect fitRect = [self.mapView mapRectThatFits:rect edgePadding:padding];
[self.mapView setVisibleMapRect:fitRect];
}
//设置路线规划折线的样式
- (BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id<BMKOverlay>)overlay {
if ([overlay isKindOfClass:[BMKPolyline class]]) {
BMKPolylineView* polylineView = [[BMKPolylineView alloc] initWithOverlay:overlay];
polylineView.strokeColor = [UIColor colorWithRed:51/255.0 green:149/255.0 blue:255/255.0 alpha:1.0];//折线颜色
polylineView.lineWidth = 6.0; //折线宽度
return polylineView;
}
return nil;
}
6.地图定位图标
@property (nonatomic, strong) BMKLocationViewDisplayParam *param;//定位图层图标
//初始化地图
- (void)initMap {
self.mapView = [[BMKMapView alloc] init];//WithFrame:CGRectZero];
self.mapView.delegate = self;
self.mapZoomLevel = 15;//地图缩放级别
[self.mapView setZoomLevel:self.mapZoomLevel];//级别,3-19
[self.view addSubview:self.mapView];
self.mapView.overlookEnabled = NO;
[self.mapView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
[self.locationManager startUpdatingLocation];//开始连续定位
[self.locationManager startUpdatingHeading];//开始获取设备朝向(GPS)
self.mapView.showsUserLocation = YES;//设定是否显示定位图层
self.mapView.userTrackingMode = BMKUserTrackingModeHeading;//普通定位模式
//定位图层自定义样式参数
self.param = [[BMKLocationViewDisplayParam alloc] init];
self.param.isAccuracyCircleShow = NO;//是否显示精度圈
self.param.canShowCallOut = NO;//是否显示气泡
self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
self.mapView.rotateEnabled = NO;//设定地图View能否支持旋转
self.param.locationViewHierarchy = LOCATION_VIEW_HIERARCHY_TOP;
self.param.locationViewOffsetY = 0;//定位图标Y轴偏移量(屏幕坐标)
[self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
}
//其他地方有区别更新
- (void)updateParam {
//代驾有单且未上车的时候设置定位图标
if ([BBXDriverInfo shareManager].driverServiceSceneMode == 1) {//代驾
if (self.orderArray) {
NSArray *tempArray = [NSArray arrayWithArray:self.orderArray];
for (OrderListModel *model in tempArray) {
if (model.order_status == Order_state_sended) {
self.param.locationViewImage = [UIImage imageNamed:@"icon_map_designatedDriver"];//有单且未上车
}
}
}
} else {
self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
}
[self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
}
#para mark -- 实现该方法,否则定位图标不出现
//连续定位回调方法(location定位结果)
- (void)BMKLocationManager:(BMKLocationManager *)manager didUpdateLocation:(BMKLocation *)location orError:(NSError *)error {
if (error) {
NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
}
if (!location) {
return;
}
// if ([BBXDiaoduSortArrayManager shareManager].openDiaoduArray.count>0) {//智能调度
// 没有添加当前位置导致定位图标不出现
// } else {
self.userLocation.location = location.location;//司机当前位置信息
[self.mapView updateLocationData:self.userLocation];//实现该方法,否则定位图标不出现
// }
}
7.逆编码
相关链接:
https://blog.csdn.net/wjchao1990/article/details/51727669
https://xiaozhuanlan.com/topic/4968730251
https://blog.csdn.net/nameis2541748437/article/details/49766105
https://www.cnblogs.com/guitarandcode/p/5783805.html(CLPlacemark属性)
//定位按钮
- (void)locationButtonAction {
self.mapView.centerCoordinate = self.userLocation.location.coordinate;
[self.mapView setZoomLevel:18];
BMKReverseGeoCodeSearchOption *reverseGeoCodeOption = [[BMKReverseGeoCodeSearchOption alloc]init];
reverseGeoCodeOption.location = self.userLocation.location.coordinate;
reverseGeoCodeOption.isLatestAdmin = YES;
//发起逆编码请求
BOOL flag = [self.search reverseGeoCode: reverseGeoCodeOption];
if (flag) {
NSLog(@"逆geo检索发送成功");
} else {
NSLog(@"逆geo检索发送失败");
}
}
//逆编码结果
- (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error {
if (error == BMK_SEARCH_NO_ERROR) {
if (searcher == self.search) {
self.adCode = result.addressDetail.adCode;
NSLog(@"速递-adCode返回结果:%@",self.adCode);
} else if (searcher == self.searchTwo) {
self.adCodeTwo = result.addressDetail.adCode;
NSLog(@"速递-adCodeTwo返回结果:%@",self.adCodeTwo);
}
} else {
NSLog(@"速递-检索失败");
}
}
8.引入相关地图文件名和协议
文件名:
#import <BaiduMapAPI_Map/BMKMapView.h>
#import <BaiduMapAPI_Map/BMKMapComponent.h>
#import <BaiduMapAPI_Utils/BMKGeometry.h>
#import <BaiduMapAPI_Base/BMKBaseComponent.h>
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
协议:
<BMKMapViewDelegate,BMKRouteSearchDelegate, BNNaviUIManagerDelegate,BMKLocationManagerDelegate,BNNaviRoutePlanDelegate>
2.高德地图相关类及方法
1.基础创建及相关使用类
创建地图、当前位置对象、定位管理类
//初始化地图
- (void)initMap {
self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.mapView];
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
self.mapView.zoomLevel = 15;//地图缩放级别
self.mapView.userTrackingMode = MAUserTrackingModeFollow;//定位用户位置的模式
self.mapView.rotateEnabled = NO;//是否支持旋转
self.mapView.rotateCameraEnabled = NO;
[self.locationManager startUpdatingLocation];//连续定位回调方法(location定位结果)
[self.locationManager startUpdatingHeading];//设备朝向回调方法;如果设备支持方向识别,则会通过代理回调方法
//定位图层图标
self.represent = [[MAUserLocationRepresentation alloc] init];
self.represent.showsAccuracyRing = NO;//精度圈是否显示
self.represent.image = kImage(@"bbx_carLocation");
[self.mapView updateUserLocationRepresentation:self.represent];
}
//司机当前位置对象
- (MAUserLocation *)userLocation {
if (!_userLocation) {
_userLocation = [[MAUserLocation alloc] init];
}
return _userLocation;
}
//定位管理类
- (AMapLocationManager *)locationManager {
if (!_locationManager) {
_locationManager = [[AMapLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager setPausesLocationUpdatesAutomatically:NO];
[_locationManager setAllowsBackgroundLocationUpdates:NO];
}
return _locationManager;
}
//路线规划
- (AMapSearchAPI *)mapSearch {
if (!_mapSearch) {
_mapSearch = [[AMapSearchAPI alloc] init];
_mapSearch.delegate = self;
}
return _mapSearch;
}
地图定位代理方法
/**
* @brief 设备方向改变时回调函数
* @param manager 定位 AMapLocationManager 类。
* @param newHeading 设备朝向。
*/
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading;
/**
* @brief 连续定位回调函数.注意:如果实现了本方法,则定位信息不会通过amapLocationManager:didUpdateLocation:方法回调。
* @param manager 定位 AMapLocationManager 类。
* @param location 定位结果。
* @param reGeocode 逆地理信息。
*/
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode;
/**
* @brief 当前位置更新回调(无论是否在导航中,只要当前位置有更新就会回调)
* @param compositeManager 导航组件类
* @param naviLocation 当前位置信息,参考 AMapNaviLocation 类
*/
//用户位置更新后,会调用此函数(userLocation 新的用户位置)
- (void)compositeManager:(AMapNaviCompositeManager *_Nonnull)compositeManager updateNaviLocation:(AMapNaviLocation *_Nullable)naviLocation;
地图代理方法
/**
* @brief 地图加载成功
* @param mapView 地图View
*/
- (void)mapViewDidFinishLoadingMap:(MAMapView *)mapView;
/**
* @brief 地图区域改变完成后会调用此接口,如实现此接口则不会触发回掉mapView:regionDidChangeAnimated:
* @param mapView 地图View
* @param animated 是否动画
* @param wasUserAction 标识是否是用户动作
*/
- (void)mapView:(MAMapView *)mapView regionDidChangeAnimated:(BOOL)animated wasUserAction:(BOOL)wasUserAction;
* @param mapView 地图View
* @param annotation 指定的标注
* @return 生成的标注View
*/
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation;
/**
* @brief 当选中一个annotation view时,调用此接口. 注意如果已经是选中状态,再次点击不会触发此回调。取消选中需调用-(void)deselectAnnotation:animated:
* @param mapView 地图View
* @param view 选中的annotation view
*/
- (void)mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view;
/**
* @brief 单击地图回调,返回经纬度
* @param mapView 地图View
* @param coordinate 经纬度
*/
//点中地图空白处会回调
- (void)mapView:(MAMapView *)mapView didSingleTappedAtCoordinate:(CLLocationCoordinate2D)coordinate;
viewForAnnotation方法中自定义气泡view可以设置的一些属性
2.发起导航算路(即开始导航)
/**
* @brief 驾车路径规划成功后的回调函数 since 6.1.0
* @param driveManager 驾车导航管理类
* @param type 路径规划类型,参考 AMapNaviRoutePlanType
*/
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type;
/**
* @brief 开始实时导航. 注意:必须在路径规划成功的情况下,才能够开始实时导航
* @return 是否成功
*/
- (BOOL)startGPSNavi;
#para mark -- 实际应用
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type {
//算路成功后开始GPS导航
[[AMapNaviDriveManager sharedInstance] startGPSNavi];
}
导航中改变终点重新导航
//后期有需求应用再总结
3.移除和添加地图的标注、移除地图覆盖物(包折线)
[self.mapView removeAnnotations:[self.mapView annotations]];//要移除的标注数组
[self.mapView addAnnotations:self.annotations];//向地图窗口添加一组标注
移除地图覆盖物(包折线)
NSArray *array = [NSArray arrayWithArray:self.mapView.overlays];
[self.mapView removeOverlays:array];//移除遮盖物
4.发起路线规划
/**
* @brief 驾车路径规划查询接口
* @param request 查询选项。具体属性字段请参考 AMapDrivingRouteSearchRequest 类。
*/
- (void)AMapDrivingRouteSearch:(AMapDrivingRouteSearchRequest *)request;
/**
* @brief 骑行路径规划查询接口 (since 4.3.0)
* @param request 查询选项。具体属性字段请参考 AMapRidingRouteSearchRequest 类。
*/
- (void)AMapRidingRouteSearch:(AMapRidingRouteSearchRequest *)request;
#para mark -- 举例:
//初始化司机路径规划
- (void)creatPlan:(BBXOrderListModel *)model {
//发起驾车路线规划
AMapDrivingRouteSearchRequest *navi = [[AMapDrivingRouteSearchRequest alloc] init];
AMapGeoPoint *endPoint;
navi.origin = [AMapGeoPoint locationWithLatitude:BBXLocationManager.shareManager.location.coordinate.latitude longitude:BBXLocationManager.shareManager.location.coordinate.longitude];//起点(司机位置)
CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:model.end_lat longitude:model.end_lng];
CLLocationDegrees lat = listLocation.coordinate.latitude;
CLLocationDegrees lng = listLocation.coordinate.longitude;
endPoint = [AMapGeoPoint locationWithLatitude:lat longitude:lng];
navi.destination = endPoint;//终点(叫代驾或叫车的人的位置)
navi.strategy = 2;//距离优先(传一个想要的规划策略给高德)
[self.mapSearch AMapDrivingRouteSearch:navi];//发起驾车路径规划查询
}
路线规划结果
/**
* @brief 路径规划查询回调
* @param request 发起的请求,具体字段参考 AMapRouteSearchBaseRequest 及其子类。
* @param response 响应结果,具体字段参考 AMapRouteSearchResponse 。
*/
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response;
#para mark -- 哪种路径规划设置
默认是驾车路径,可以通过判断request设置,比如骑行 AMapRidingRouteSearchRequest,驾车 AMapDrivingRouteSearchRequest
5.画折线(起终点-骑行例子)
相关链接:
https://lbs.amap.com/api/ios-sdk/guide/draw-on-map/draw-polyline
https://www.jianshu.com/p/79b455c74679
//发起骑行路线规划
- (void)updateViewByShowingOrderListModel:(BBXOrderListModel *)orderListModel {
//发起骑行路线规划
AMapRidingRouteSearchRequest *navi = [[AMapRidingRouteSearchRequest alloc] init];
AMapGeoPoint *endPoint;
navi.origin = [AMapGeoPoint locationWithLatitude:BBXLocationManager.shareManager.location.coordinate.latitude longitude:BBXLocationManager.shareManager.location.coordinate.longitude];//起点
CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
CLLocationDegrees lat = listLocation.coordinate.latitude;
CLLocationDegrees lng = listLocation.coordinate.longitude;
endPoint = [AMapGeoPoint locationWithLatitude:lat longitude:lng];
navi.destination = endPoint;//终点(叫代驾或叫车的人的位置)
navi.type = 1;//推荐路线
[self.mapSearch AMapRidingRouteSearch:navi];//发起骑行路径规划查询
}
#para mark -- 途经点相关
//途经点 AMapGeoPoint 数组,目前最多支持6个途经点
@property (nonatomic, copy) NSArray<AMapGeoPoint *> *waypoints;
#pragma mark -- 高德路线规划
//骑行路线规划结果
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response {
NSArray *array = [NSArray arrayWithArray:self.mapView.annotations];
[self.mapView removeAnnotations:array];
array = [NSArray arrayWithArray:self.mapView.overlays];
[self.mapView removeOverlays:array];//移除遮盖物
if (response.route == nil) {//路线规划出错(太近检索失败)
AMapRoute *route = response.route;
AMapPath *path = [route.paths firstObject];
//添加起点标注
BBXPassAnnotation *startAnnotation = [[BBXPassAnnotation alloc] init];
startAnnotation.type = @"start";
CLLocation * driverLocation = [BBXLocationManager shareManager].location;
startAnnotation.coordinate = driverLocation.coordinate;
[self.mapView addAnnotation:startAnnotation];
//添加终点标注
BBXPassAnnotation *endAnnotation = [[BBXPassAnnotation alloc] init];
endAnnotation.type = @"end";
CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
endAnnotation.coordinate = listLocation.coordinate;
[self.mapView addAnnotation:endAnnotation];
//泡泡弹出的地点(叫代驾的人所在的点)
BBXPassAnnotation *passAn = [[BBXPassAnnotation alloc] init];
passAn.type = @"Pop";
passAn.title = @"距离车主1.0米";
CLLocation *palocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
passAn.coordinate = palocation.coordinate;
[self.mapView addAnnotation:passAn];
//画路线规划的折线
MAPolyline *polyline = [self polylinesForPath:path];//轨迹点
[self.mapView addOverlay:polyline];//画路线规划的折线
[self mapViewFitPolyLine:polyline];//根据polyline设置地图范围
return;
} else {
AMapPath *path = [response.route.paths firstObject];
NSInteger mile = path.distance;
if (mile>=0 && mile<=100.0) {//100米认为比较近
[BBXProgressHUD showInfo:@"距离太近,无法规划路线"];
return;
}
//路线规划成功
if ([request isKindOfClass:[AMapRidingRouteSearchRequest class]]) {//骑行路径规划
AMapRoute *route = response.route;
AMapPath *path = [route.paths firstObject];
NSInteger size = [path.steps count];
for (int i = 0; i < size; i++) {
if (i == 0) {
//添加起点标注
BBXPassAnnotation *startAnnotation = [[BBXPassAnnotation alloc] init];
startAnnotation.type = @"start";
CLLocation *startLocat = [[CLLocation alloc] initWithLatitude:route.origin.latitude longitude:route.origin.longitude];
startAnnotation.coordinate = startLocat.coordinate;
[self.mapView addAnnotation:startAnnotation];
}
if(i == size-1) {
//添加终点标注
BBXPassAnnotation *endAnnotation = [[BBXPassAnnotation alloc] init];
endAnnotation.type = @"end";
CLLocation *endLocat = [[CLLocation alloc] initWithLatitude:route.destination.latitude longitude:route.destination.longitude];
endAnnotation.coordinate = endLocat.coordinate;
[self.mapView addAnnotation:endAnnotation];
}
}
//泡泡弹出的地点(叫代驾的人所在的点)
BBXPassAnnotation *passAn = [[BBXPassAnnotation alloc] init];
passAn.type = @"Pop";
CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
passAn.coordinate = listLocation.coordinate;
float distance = path.distance;
if (distance >= 100.0) {
NSString *kmString = [BBXMileageConvert meterTurnKilometreOneDecimalWith:distance];//米转公里
passAn.title = [NSString stringWithFormat:@"距离车主%@公里", kmString];
} else {
if (distance<=10.0) {
distance = 1.0;
passAn.title = [NSString stringWithFormat:@"距离车主%.1f米", distance];
} else {
passAn.title = [NSString stringWithFormat:@"距离车主%.1f米", distance];
}
}
[self.mapView addAnnotation:passAn];
//画路线规划的折线
MAPolyline *polyline = [self polylinesForPath:path];//轨迹点
[self.mapView addOverlay:polyline];//画路线规划的折线
[self mapViewFitPolyLine:polyline];//根据polyline设置地图范围
}
}
}
//路径规划检索失败
- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error {
NSLog(@"Error: %@", error);
}
//路线解析-轨迹点
- (MAPolyline *)polylinesForPath:(AMapPath *)path {
if (path == nil || path.steps.count == 0){
return nil;
}
NSMutableString *polylineMutableString = [@"" mutableCopy];
for (AMapStep *step in path.steps) {
[polylineMutableString appendFormat:@"%@;",step.polyline];
}
NSUInteger count = 0;
CLLocationCoordinate2D *coordinates = [self coordinatesForString:polylineMutableString
coordinateCount:&count
parseToken:@";"];
MAPolyline *polyline = [MAPolyline polylineWithCoordinates:coordinates count:count];
free(coordinates), coordinates = NULL;
return polyline;
}
//解析经纬度
- (CLLocationCoordinate2D *)coordinatesForString:(NSString *)string
coordinateCount:(NSUInteger *)coordinateCount
parseToken:(NSString *)token{
if (string == nil){
return NULL;
}
if (token == nil){
token = @",";
}
NSString *str = @"";
if (![token isEqualToString:@","]) {
str = [string stringByReplacingOccurrencesOfString:token withString:@","];
} else {
str = [NSString stringWithString:string];
}
NSArray *components = [str componentsSeparatedByString:@","];
NSUInteger count = [components count] / 2;
if (coordinateCount != NULL){
*coordinateCount = count;
}
CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D*)malloc(count * sizeof(CLLocationCoordinate2D));
for (int i = 0; i < count; i++){
coordinates[i].longitude = [[components objectAtIndex:2 * i] doubleValue];
coordinates[i].latitude = [[components objectAtIndex:2 * i + 1] doubleValue];
}
return coordinates;
}
//根据polyline设置地图范围
- (void)mapViewFitPolyLine:(MAPolyline *) polyLine {
CGFloat leftTopX, leftTopY, rightBottomX, rightBottomY;
if (polyLine.pointCount < 1) {
return;
}
MAMapPoint pt = polyLine.points[0];//BMKMapPoint
// 左上角顶点
leftTopX = pt.x;
leftTopY = pt.y;
// 右下角顶点
rightBottomX = pt.x;
rightBottomY = pt.y;
for (int i = 1; i < polyLine.pointCount; i++) {
MAMapPoint pt = polyLine.points[i];
leftTopX = pt.x < leftTopX ? pt.x : leftTopX;
leftTopY = pt.y < leftTopY ? pt.y : leftTopY;
rightBottomX = pt.x > rightBottomX ? pt.x : rightBottomX;
rightBottomY = pt.y > rightBottomY ? pt.y : rightBottomY;
}
MAMapRect rect;//BMKMapRect
rect.origin = MAMapPointMake(leftTopX, leftTopY);//BMKMapPointMake
rect.size = MAMapSizeMake(rightBottomX - leftTopX, rightBottomY - leftTopY);//BMKMapSizeMake
UIEdgeInsets padding = UIEdgeInsetsMake(175, 175, 175, 175);//这个自己根据需求调整
MAMapRect fitRect = [self.mapView mapRectThatFits:rect edgePadding:padding];
[self.mapView setVisibleMapRect:fitRect];
}
//设置折线的样式
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id<MAOverlay>)overlay {
if ([overlay isKindOfClass:[MAPolyline class]]){
MAPolylineRenderer *polylineView = [[MAPolylineRenderer alloc] initWithOverlay:overlay];//BMKPolylineView
polylineView.strokeColor = [UIColor colorWithRed:51/255.0 green:149/255.0 blue:255/255.0 alpha:1.0];//折线颜色
polylineView.lineWidth = 6.0; //折线宽度
polylineView.lineJoinType = kMALineJoinRound;//连接类型
return polylineView;//BMKOverlayView
}
return nil;
}
6.地图定位图标
@property (nonatomic, strong) MAUserLocationRepresentation *represent;//定位图层图标
//初始化地图
- (void)initMap {
self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.mapView];
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
self.mapView.zoomLevel = 15;//地图缩放级别
self.mapView.userTrackingMode = MAUserTrackingModeFollow;//定位用户位置的模式
self.mapView.rotateEnabled = NO;//是否支持旋转
self.mapView.rotateCameraEnabled = NO;
[self.locationManager startUpdatingLocation];//连续定位回调方法(location定位结果)
[self.locationManager startUpdatingHeading];//设备朝向回调方法;如果设备支持方向识别,则会通过代理回调方法
//定位图层图标
self.represent = [[MAUserLocationRepresentation alloc] init];
self.represent.showsAccuracyRing = NO;//精度圈是否显示
self.represent.image = kImage(@"bbx_carLocation");
[self.mapView updateUserLocationRepresentation:self.represent];
}
//其他地方有区别更新
- (void)updateParam {
//代驾有单且未上车的时候设置定位图标
if ([BBXDriverInfo sharedInstance].driverServiceSceneMode == 1) {//代驾
if (self.orderArray) {
NSArray *tempArray = [NSArray arrayWithArray:self.orderArray];
for (BBXOrderListModel *model in tempArray) {
if (model.order_status == Order_state_sended) {
self.represent.image = kImage(@"icon_map_designatedDriver");//有单且未上车
} else {
self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
}
}
} else {
self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
}
} else {
self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
}
[self.mapView updateUserLocationRepresentation:self.represent];//动态定制我的位置样式
}
7.逆编码
相关链接:https://blog.csdn.net/chongran9230/article/details/100804174
8.引入相关地图文件名和协议
文件名:
#import <AMapNaviKit/AMapNaviKit.h>
#import <AMapSearchKit/AMapSearchKit.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <AMapLocationKit/AMapLocationKit.h>
协议:
<MAMapViewDelegate, AMapSearchDelegate, AMapLocationManagerDelegate>
3.地图SDK导入工程及plist权限添加
百度地图相关SDK:地图、导航、定位、鹰眼 百度地图使用相关权限 高德地图相关SDK:地图、导航、定位、鹰眼 高德地图使用相关权限判断手机App地图定位权限是否有打开:
举例:如果App定位权限不是“始终”,则提醒打开
- (void)jugdeIsOpenAlwaysLocation {
//如果用户选择的定位权限不是“始终”,则弹窗让用户修改权限
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"定位权限请选择“始终”,否则服务无法使用!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self.navigationController popToRootViewControllerAnimated:YES];
}];
UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"前往开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
return;
}
}