地图之简单认识相关类及方法

2022-07-21  本文已影响0人  Kevin_wzx

目录

百度地图相关类及方法
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;
    }
}
上一篇下一篇

猜你喜欢

热点阅读