开发 iOS 导航SDK 概述

概述 最后更新时间: 2021年11月04日

重要:由于个人信息保护法的实施,从导航8.1.0版本起对旧版本SDK不兼容,请务必确保调用SDK任何接口前先调用更新隐私合规updatePrivacyShow、updatePrivacyAgree两个接口,否则可能导致功能不可用等异常情况。具体可参考开发指南-隐私合规说明传入相关参数。

iOS导航SDK是一款针对在线导航的产品,产品功能涵盖了路径规划、专业导航、UI界面定制、导航组件、货车导航等。并且,导航路径规划与实时交通信息相结合,力求为用户提供更加合理、准确、人性化的导航服务。应用场景包括但不限于O2O、网约车出行、货运物流快递等。

在您接入 SDK 的前中后整个过程中,我们都会提供全方位的支持,包括官网文档、官方Demo商务合作工单、大客户钉钉群、现场支持等。

面向的读者

iOS导航SDK是提供给具有一定iOS编程经验和了解面向对象概念的读者使用的。

  • 模拟导航
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        [self initDriveView];
        
        [self initDriveManager];
        
        [self calculateRoute];
    }
    
    - (void)initDriveManager
    {
        //请在 dealloc 函数中或者页面pop时,执行 [AMapNaviDriveManager destroyInstance] 来销毁单例
        [[AMapNaviDriveManager sharedInstance] setDelegate:self];
        
        //将driveView添加为导航数据的Representative,使其可以接收到导航诱导数据
        [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.driveView];
    }
    
    - (void)initDriveView
    {
        if (self.driveView == nil)
        {
            self.driveView = [[AMapNaviDriveView alloc] initWithFrame:self.view.bounds];
            self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
            [self.driveView setDelegate:self];
            [self.driveView setShowGreyAfterPass:YES];
            [self.driveView setAutoZoomMapLevel:YES];
            [self.driveView setMapViewModeType:AMapNaviViewMapModeTypeNight];
            [self.driveView setTrackingMode:AMapNaviViewTrackingModeCarNorth];
            
            [self.view addSubview:self.driveView];
        }
    }
    
    - (void)calculateRoute
    {
        //进行路径规划
        [[AMapNaviDriveManager sharedInstance]  calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                    endPoints:@[self.endPoint]
                                                    wayPoints:nil
                                              drivingStrategy:AMapNaviDrivingStrategySingleDefault];
    }
    
    #pragma mark - AMapNaviDriveManager Delegate
    
    - (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager
    {
        NSLog(@"onCalculateRouteSuccess");
        
        //算路成功后进行模拟导航
        [[AMapNaviDriveManager sharedInstance]  startEmulatorNavi];
    }
  • 导航组件
    @interface CompositeViewController () <AMapNaviCompositeManagerDelegate>
    
    @property (nonatomic, strong) AMapNaviCompositeManager *compositeManager;
    
    @end
    
    // init 
    - (AMapNaviCompositeManager *)compositeManager {
        if (!_compositeManager) {
            _compositeManager = [[AMapNaviCompositeManager alloc] init];  // 初始化
            _compositeManager.delegate = self;  // 如果需要使用AMapNaviCompositeManagerDelegate的相关回调(如自定义语音、获取实时位置等),需要设置delegate
        }
        return _compositeManager;
    }
    
    - (void)routePlanAction {
        [self.compositeManager presentRoutePlanViewControllerWithOptions:nil];  // 通过present的方式显示路线规划页面
    }
  • 货车导航组件
    @interface CompositeTrunkViewController () <AMapNaviCompositeManagerDelegate>
    
    @property (nonatomic, strong) AMapNaviCompositeManager *compositeManager;
    
    @end
    
    // init
    - (AMapNaviCompositeManager *)compositeManager {
        if (!_compositeManager) {
            _compositeManager = [[AMapNaviCompositeManager alloc] init];  // 初始化
            _compositeManager.delegate = self;  // 如果需要使用AMapNaviCompositeManagerDelegate的相关回调(如自定义语音、获取实时位置等),需要设置delegate
        }
        return _compositeManager;
    }
    
    - (void)trunkDemo {
        
        AMapNaviCompositeUserConfig *config = [[AMapNaviCompositeUserConfig alloc] init];
        
        AMapNaviVehicleInfo *info = [[AMapNaviVehicleInfo alloc] init];
        info.vehicleId = @"京N66Y66";
        info.type = 1;  // 设置车辆类型为货车
        info.size = 4;
        info.height = 3.9;
        info.length = 15;
        info.weight = 45;
        info.load = 50;
        info.width = 3;
        info.axisNums = 6;
        [config setVehicleInfo:info];
        
        [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeStart location:[AMapNaviPoint locationWithLatitude:39.902896 longitude:116.42792] name:@"北京站" POIId:nil];
        [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeWay location:[AMapNaviPoint locationWithLatitude:39.975642 longitude:116.306332] name:@"苏州街(地铁站)" POIId:nil];
        [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeEnd location:[AMapNaviPoint locationWithLatitude:39.894914 longitude:116.322062] name:@"北京西站" POIId:nil];
        
        [self.compositeManager presentRoutePlanViewControllerWithOptions:config];
    }
  • AMapNaviDriveView完全自定义UI和图面
    @interface CustomUIViewController () <AMapNaviDriveManagerDelegate, AMapNaviDriveDataRepresentable, AMapNaviDriveViewDelegate>
    
    @property (nonatomic, strong) AMapNaviPoint *startPoint;
    @property (nonatomic, strong) AMapNaviPoint *endPoint;
    @property (nonatomic, strong) AMapNaviDriveView *driveView;
    
    //xib views
    @property (nonatomic, weak) IBOutlet UIView *topInfoBgView;
    @property (nonatomic, weak) IBOutlet UIImageView *topTurnImageView;
    @property (nonatomic, weak) IBOutlet UILabel *topRemainLabel;
    @property (nonatomic, weak) IBOutlet UILabel *topRoadLabel;
    @property (nonatomic, weak) IBOutlet UIImageView *crossImageView;
    
    @property (nonatomic, weak) IBOutlet UIView *routeRemianInfoView;
    @property (nonatomic, weak) IBOutlet UILabel *routeRemainInfoLabel;
    @property (nonatomic, weak) IBOutlet UIButton *rightBrowserBtn;
    @property (nonatomic, weak) IBOutlet UIView *startEndPointInfoView;
    @property (nonatomic, weak) IBOutlet AMapNaviTrafficBarView *trafficBarView;
    @property (nonatomic, weak) IBOutlet UIButton *rightTrafficBtn;
    
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint *topInfoViewTopSpace;
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint *bottomInfoLabelBottomSpace;
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint *topInfoViewLeftSpace;
    @property (nonatomic, weak) IBOutlet NSLayoutConstraint *crossImageViewHeight;
    
    
    @end
    
    @implementation CustomUIViewController
    
    #pragma mark - LifeCycle
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor whiteColor];
        
        //初始化xib界面上的元素
        [self updateViewsWhenInit];
        
        //为了方便展示,选择了固定的起终点
        self.startPoint = [AMapNaviPoint locationWithLatitude:39.993135 longitude:116.474175];
        self.endPoint   = [AMapNaviPoint locationWithLatitude:39.908791 longitude:116.321257];
        
        //driveView
        self.driveView = [[AMapNaviDriveView alloc] initWithFrame:self.view.bounds];
        self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        self.driveView.delegate = self;
        self.driveView.showUIElements = NO;
        self.driveView.showGreyAfterPass = YES;
        self.driveView.autoZoomMapLevel = YES;
        self.driveView.mapViewModeType = AMapNaviViewMapModeTypeNight;
        self.driveView.autoSwitchShowModeToCarPositionLocked = YES;
        self.driveView.trackingMode = AMapNaviViewTrackingModeCarNorth;
        self.driveView.logoCenter = CGPointMake(self.driveView.logoCenter.x + 2, self.driveView.logoCenter.y + 60);
        [self.driveView setCarImage:[UIImage imageNamed:@"customCar"]];
        [self.view addSubview:self.driveView];
        [self.view sendSubviewToBack:self.driveView];
        [self updateMapViewScreenAnchor];  // 设置锚点
        
        //driveManager 请在 dealloc 函数中执行 [AMapNaviDriveManager destroyInstance] 来销毁单例
        [[AMapNaviDriveManager sharedInstance] setDelegate:self];
        [[AMapNaviDriveManager sharedInstance] setIsUseInternalTTS:YES];
        
        [[AMapNaviDriveManager sharedInstance] setAllowsBackgroundLocationUpdates:YES];
        [[AMapNaviDriveManager sharedInstance] setPausesLocationUpdatesAutomatically:NO];
        
        //将self 、driveView、trafficBarView 添加为导航数据的Representative,使其可以接收到导航诱导数据
        [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.driveView];
        [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.trafficBarView];
        [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self];
        
        //算路
        [[AMapNaviDriveManager sharedInstance] calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                                        endPoints:@[self.endPoint]
                                                                        wayPoints:nil
                                                                  drivingStrategy:AMapNaviDrivingStrategySingleDefault];
        
    }
    
    - (void)dealloc {
        [[AMapNaviDriveManager sharedInstance] stopNavi];
        [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self.driveView];
        [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self.trafficBarView];
        [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self];
        [[AMapNaviDriveManager sharedInstance] setDelegate:nil];
        
        BOOL success = [AMapNaviDriveManager destroyInstance];
        NSLog(@"单例是否销毁成功 : %d",success);
    }
    
    #pragma mark - Setup
    
    - (void)updateViewsWhenInit {
        
        self.routeRemianInfoView.layer.cornerRadius = 5;
        self.startEndPointInfoView.layer.cornerRadius = 5;
        self.trafficBarView.borderWidth = 2.5;
        self.crossImageViewHeight.constant = MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) * 16.0 / 25.0;  //路口放大图宽高为25:16
        
        if ([self isiPhoneX]) {
            self.topInfoViewTopSpace.constant = 30;
            self.bottomInfoLabelBottomSpace.constant = 12;
            self.topInfoViewLeftSpace.constant = 24;
        }
        
        //hide
        self.topInfoBgView.hidden = self.routeRemianInfoView.hidden = YES;
        self.crossImageView.hidden = YES;
    }
    
    //更新地图锚点
    - (void)updateMapViewScreenAnchor {
        
        [self.view layoutIfNeeded];
        
        CGFloat x = 0.5;
        CGFloat y = 0.75;
        
        if(self.driveView.isLandscape) {  //横屏模式
            CGFloat xStart = self.trafficBarView.frame.origin.x + self.trafficBarView.frame.size.width;
            CGFloat xEnd = self.driveView.bounds.size.width - 80;
            if (self.crossImageView.image) {
                xStart = self.trafficBarView.frame.origin.x - 10;
                xEnd = self.driveView.bounds.size.width;
                y = 0.7;
            } else {
                y = 0.55;
            }
            CGFloat xAreaMiddleInAll = (xEnd - xStart) / 2 + xStart;
            x = xAreaMiddleInAll / self.driveView.bounds.size.width;
        }
        
        if (x <= 0 || x >= 1 ) {
            x = 0.5;
        }
        
        if (self.driveView.screenAnchor.x != x || self.driveView.screenAnchor.y != y) {
            self.driveView.screenAnchor = CGPointMake(x, y);
        }
    }
    
    //处理路口放大图
    - (void)handleWhenCrossImageShowAndHide:(UIImage *)crossImage {
        if (crossImage && self.driveView.showMode == AMapNaviDriveViewShowModeCarPositionLocked) {
            self.crossImageView.hidden = NO;
            self.crossImageView.image = crossImage;
            self.rightBrowserBtn.hidden = YES;
            self.rightTrafficBtn.hidden = YES;
            self.routeRemianInfoView.hidden = YES;
            self.trafficBarView.hidden = YES;
            self.startEndPointInfoView.hidden = YES;
        } else {
            self.crossImageView.hidden = YES;
            self.crossImageView.image = nil;
            self.rightBrowserBtn.hidden = NO;
            self.rightTrafficBtn.hidden = NO;
            self.routeRemianInfoView.hidden = NO;
            self.trafficBarView.hidden = NO;
            self.startEndPointInfoView.hidden = NO;
        }
        [self updateMapViewScreenAnchor];
    }
    
    #pragma mark - AMapNaviDriveManager Delegate
    
    - (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager {
        NSLog(@"onCalculateRouteSuccess");
        
        //算路成功后开始导航
        [[AMapNaviDriveManager sharedInstance] startEmulatorNavi];
    }
    
    #pragma mark - AMapNaviDriveDataRepresentable
    
    //诱导信息
    - (void)driveManager:(AMapNaviDriveManager *)driveManager updateNaviInfo:(AMapNaviInfo *)naviInfo {
        if (naviInfo) {
            
            if (self.topInfoBgView.hidden) {
                self.topInfoBgView.hidden = self.routeRemianInfoView.hidden = NO;
            }
            
            self.topRemainLabel.text = [NSString stringWithFormat:@"%@后",[self normalizedRemainDistance:naviInfo.segmentRemainDistance]];
            self.topRoadLabel.text = naviInfo.nextRoadName;
            
            NSString *remainTime = [self normalizedRemainTime:naviInfo.routeRemainTime];
            NSString *remainDis = [self normalizedRemainDistance:naviInfo.routeRemainDistance];
            self.routeRemainInfoLabel.text = [NSString stringWithFormat:@"剩余 %@ %@",remainDis,remainTime];
            
        }
    }
    
    //转向图标
    - (void)driveManager:(AMapNaviDriveManager *)driveManager updateTurnIconImage:(UIImage *)turnIconImage turnIconType:(AMapNaviIconType)turnIconType {
        if (turnIconImage) {
            self.topTurnImageView.image = turnIconImage;
        }
    }
    
    //显示路口放大图
    - (void)driveManager:(AMapNaviDriveManager *)driveManager showCrossImage:(UIImage *)crossImage {
        [self handleWhenCrossImageShowAndHide:crossImage];
    }
    
    //隐藏路口放大图
    - (void)driveManagerHideCrossImage:(AMapNaviDriveManager *)driveManager {
        [self handleWhenCrossImageShowAndHide:nil];
    }
    
    #pragma mark - AMapNaviDriveViewDelegate
    
    - (void)driveView:(AMapNaviDriveView *)driveView didChangeOrientation:(BOOL)isLandscape {
        NSLog(@"didChangeOrientation:%ld", (long)isLandscape);
        [self updateMapViewScreenAnchor];
        if (self.driveView.showMode == AMapNaviDriveViewShowModeOverview) {  //如果是全览状态,重新适应一下全览路线,让其均可见
            [self.driveView updateRoutePolylineInTheVisualRangeWhenTheShowModeIsOverview];
        }
    }
    
    - (void)driveView:(AMapNaviDriveView *)driveView didChangeShowMode:(AMapNaviDriveViewShowMode)showMode {
        if (showMode == AMapNaviDriveViewShowModeOverview) {
            self.rightBrowserBtn.selected = YES;
        } else {
            self.rightBrowserBtn.selected = NO;
        }
        
        if (showMode != AMapNaviDriveViewShowModeCarPositionLocked) {  //非锁车,隐藏路口放大图
            [self handleWhenCrossImageShowAndHide:nil];
        }
    }
    
    //返回边界Padding,来规定可见区域
    - (UIEdgeInsets)driveViewEdgePadding:(AMapNaviDriveView *)driveView {
        
        //top left bottom right
        CGFloat offset = 20;
        CGFloat top = self.routeRemianInfoView.frame.origin.y + self.routeRemianInfoView.bounds.size.height + offset;
        CGFloat left = 40;
        CGFloat bottom = self.view.bounds.size.height - self.startEndPointInfoView.frame.origin.y + offset;
        CGFloat right = 80;
        if (self.driveView.isLandscape) {
            top =  offset;
            left = self.trafficBarView.frame.origin.x + self.trafficBarView.frame.size.width + offset;
            bottom = self.view.bounds.size.height - self.startEndPointInfoView.frame.origin.y + offset;
            right = 80;
        }
        
        UIEdgeInsets insets = UIEdgeInsetsMake(top, left, bottom, right);
    
        return insets;
    }
    
    #pragma mark - Button Click
    
    - (IBAction)closeBtnClick:(id)sender {
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (IBAction)trafficBtnClick:(id)sender {
        UIButton *btn = (UIButton *)sender;
        self.driveView.mapShowTraffic = !self.driveView.mapShowTraffic;
        btn.selected = !self.driveView.mapShowTraffic;
    }
    
    - (IBAction)browserBtn:(id)sender {
        if (self.driveView.showMode == AMapNaviDriveViewShowModeOverview) {
            self.driveView.showMode = AMapNaviDriveViewShowModeCarPositionLocked;
        } else {
            self.driveView.showMode = AMapNaviDriveViewShowModeOverview;
        }
    }
    
    #pragma mark - Utility
    
    - (BOOL)isiPhoneX {
        return [UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO;
    }
    
    - (NSString *)normalizedRemainDistance:(NSInteger)remainDistance {
        
        if (remainDistance < 0) {
            return nil;
        }
        
        if (remainDistance >= 1000) {
            CGFloat kiloMeter = remainDistance / 1000.0;
            return [NSString stringWithFormat:@"%.1f公里", kiloMeter];
        } else {
            return [NSString stringWithFormat:@"%ld米", (long)remainDistance];
        }
    }
    
    - (NSString *)normalizedRemainTime:(NSInteger)remainTime {
        if (remainTime < 0) {
            return nil;
        }
        
        if (remainTime < 60) {
            return [NSString stringWithFormat:@"< 1分钟"];
        } else if (remainTime >= 60 && remainTime < 60*60) {
            return [NSString stringWithFormat:@"%ld分钟", (long)remainTime/60];
        } else {
            NSInteger hours = remainTime / 60 / 60;
            NSInteger minute = remainTime / 60 % 60;
            if (minute == 0) {
                return [NSString stringWithFormat:@"%ld小时", (long)hours];
            } else {
                return [NSString stringWithFormat:@"%ld小时%ld分钟", (long)hours, (long)minute];
            }
        }
    }

兼容性

v6.4.0及以上版本支持iOS 8.0及以上系统

开发者建议

对于高德开放平台提供的地图API/SDK,若您以非商业目的使用,则均可免费使用 。若您以商业目的使用,则您需事先从高德获取商用授权。您需要先申请Key,才能使用该服务。关于具体使用规则,请参阅《高德地图开放平台服务协议》获得详细信息。 

返回顶部 示例中心 常见问题 智能客服 公众号
二维码