[iOS]应用内跳转到各类地图进行路线规划

本文介绍了一种在iOS应用中集成多种地图服务的方法,通过URI跳转实现苹果、百度、高德、腾讯及谷歌地图的路线规划功能。文章提供了详细的代码示例,并说明了iOS9之后的应用适配技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[OC]

Demo:应用内跳转到各类地图-iOS代码类资源-CSDN下载

首先,使用苹果自带的地图规划路线,需要开启定位权限获取当前位置。

另外,iOS9之后,需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。我们需要根据判断是否安装,选择是否在弹出的表单中展示相应的地图跳转。

LSApplicationQueriesSchemes
高德地图    iosamap
百度地图    baidumap
腾讯地图    qqmap
谷歌地图    comgooglemaps

Model

#import <Foundation/Foundation.h>

@interface GAAddressModel : NSObject
@property (strong, nonatomic) NSString *dShopName;  // 商铺名称
@property (strong, nonatomic) NSString *dAddress;   // 地址
@property (strong, nonatomic) NSString *dLng;       // 经度
@property (strong, nonatomic) NSString *dLat;       // 纬度

@end

UIViewController

#import <UIKit/UIKit.h>
#import "GAMapDetailsViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotationView.h>
#import "QYAnnotation.h"
#import "MKMapView+ZoomLevel.h"
#import "DestinationMode.h"
#import "GAAddressModel.h"

@interface GAMapDetailsViewController : UIViewController <MKMapViewDelegate> {
    UIView            *uiView;
    CLLocationManager *locationManager;
    MKMapView         *maMapView;
    MKAnnotationView  *annotationView;
    DestinationMode   *destinationMode;
}
@property (weak, nonatomic) GAAddressModel *dataModel;

@end

@implementation GAMapDetailsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initMap];
}

// 初始化地图
- (void)initMap {
    destinationMode = [DestinationMode new];
    destinationMode.destinationName = _dataModel.dShopName;
    destinationMode.destinationDesc = _dataModel.dAddress;
    destinationMode.destinationLongitude = _dataModel.dLng;
    destinationMode.destinationLatitude = _dataModel.dLat;
    maMapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];
    [self.view addSubview:maMapView];
    // 设置代理
    maMapView.delegate = self;
    // 请求定位服务
    locationManager = [[CLLocationManager alloc] init];
    if (![CLLocationManager locationServicesEnabled]||[CLLocationManager authorizationStatus]!=kCLAuthorizationStatusAuthorizedWhenInUse) {
        [locationManager requestWhenInUseAuthorization];
    }
    // 用户位置追踪(用户位置追踪用于标记用户当前位置,此时会调用定位服务)
    maMapView.userTrackingMode = MKUserTrackingModeFollow;
    // 设置地图类型
    maMapView.mapType = MKMapTypeStandard;
    [self addAnnotation];
    [self.view bringSubviewToFront:_returnBut];
}

// 添加大头针
- (void)addAnnotation {
    CLLocationCoordinate2D location1 = CLLocationCoordinate2DMake(destinationMode.destinationLatitude.floatValue, destinationMode.destinationLongitude.floatValue);
    QYAnnotation *annotation1 = [[QYAnnotation alloc] init];
    annotation1.title = destinationMode.destinationName;
    annotation1.subtitle = destinationMode.destinationDesc;
    annotation1.coordinate = location1;
    [maMapView setCenterCoordinate:location1 zoomLevel:10 animated:NO];
    [maMapView addAnnotation:annotation1];
    [maMapView selectAnnotation:annotation1 animated:YES];
}

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
    
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    // 由于当前位置的标注也是一个大头针,所以此时需要判断,此代理方法返回nil使用默认大头针视图
    if ([annotation isKindOfClass:[QYAnnotation class]]) {
        static NSString *key1 = @"QYAnnotation";
        annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:key1];
        // 如果缓存池中不存在则新建
        if (!annotationView) {
            annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:key1];
            // 允许交互点击
            annotationView.canShowCallout = true;
            // 定义详情视图偏移量
            annotationView.calloutOffset = CGPointMake(0, 1);
            UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 50)];
            [btn setBackgroundImage:[UIImage imageNamed:@"common_green_line"] forState:UIControlStateNormal];
            [btn setTitle:@"到这去" forState:UIControlStateNormal];
            [btn addTarget:self action:@selector(turnAction:) forControlEvents:UIControlEventTouchUpInside];
            // 定义详情左侧视图
            annotationView.rightCalloutAccessoryView = btn;
            annotationView.selected = YES;
        }
        // 修改大头针视图
        // 重新设置此类大头针视图的大头针模型(因为有可能是从缓存池中取出来的,位置是放到缓存池时的位置)
        annotationView.annotation = annotation;
        // 设置大头针视图的图片
        annotationView.image = [UIImage imageNamed:@"common_map_site"];
        return annotationView;
    } else {
        return nil;
    }
}

// 到这去
- (void)turnAction:(id)sender {
    NSString *tempMsg = @"导航到店铺的位置";
    if (![destinationMode.destinationName isEqualToString:@""]) {
        tempMsg = [NSString stringWithFormat:@"导航到“%@”的位置",destinationMode.destinationName];
    }
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:tempMsg preferredStyle:UIAlertControllerStyleActionSheet];
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"http://maps.apple.com/"]]) {
        UIAlertAction *appleMapAction = [UIAlertAction actionWithTitle:@"苹果地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self doAppleNavigation];
        }];
        [alert addAction:appleMapAction];
    }
    
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
        UIAlertAction *baiduMapAction = [UIAlertAction actionWithTitle:@"百度地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self doBaiduNavigation];
        }];
        [alert addAction:baiduMapAction];
    }
    
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
        UIAlertAction *gaodeMapAction = [UIAlertAction actionWithTitle:@"高德地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self doGaodeNavigation];
        }];
        [alert addAction:gaodeMapAction];
    }

    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
        UIAlertAction *googleMapAction = [UIAlertAction actionWithTitle:@"腾讯地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self doQQNavigation];
        }];
        [alert addAction:googleMapAction];
    }

    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
        UIAlertAction *googleMapAction = [UIAlertAction actionWithTitle:@"谷歌地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self doGoogleNavigation];
        }];
        [alert addAction:googleMapAction];
    }

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    }];
    [alert addAction:cancelAction];
    [self presentViewController:alert animated:YES completion:nil];
}

/**
 * 苹果地图路线规划
 * 文档:https://developer.apple.com/documentation/mapkit/mkmapitem
 */
- (void)doAppleNavigation {
    NSDictionary *options = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard),MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving};
    CLLocationCoordinate2D fromCoordinate = maMapView.userLocation.location.coordinate;
    CLLocationCoordinate2D toCoordinate = CLLocationCoordinate2DMake(destinationMode.destinationLatitude.floatValue, destinationMode.destinationLongitude.floatValue);
    MKPlacemark *fromPlacemark = [[MKPlacemark alloc] initWithCoordinate:fromCoordinate
                                                       addressDictionary:nil];
    MKPlacemark *toPlacemark = [[MKPlacemark alloc] initWithCoordinate:toCoordinate
                                                       addressDictionary:nil];
    MKMapItem *fromItem = [[MKMapItem alloc] initWithPlacemark:fromPlacemark];
    fromItem.name = @"我的位置";
    MKMapItem *toItem = [[MKMapItem alloc] initWithPlacemark:toPlacemark];
    toItem.name = destinationMode.destinationName;
    [MKMapItem openMapsWithItems:@[fromItem,toItem] launchOptions:options];
}

/**
 * 百度地图路线规划
 * 文档:http://lbsyun.baidu.com/index.php?title=uri/api/ios
 */
- (void)doBaiduNavigation {
    NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=name:%@|latlng:%f,%f&mode=driving&coord_type=gcj02",destinationMode.destinationName,destinationMode.destinationLatitude.floatValue, destinationMode.destinationLongitude.floatValue] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}

/**
 * 高德地图路线规划
 * 文档:http://lbs.amap.com/api/amap-mobile/guide/ios/route
 */
- (void)doGaodeNavigation {
    NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
    NSString *tempAppName = [NSString stringWithFormat:@"%@",infoDic[@"CFBundleDisplayName"]];
    NSString *tempUrlScheme = @"demoURL://";
    
    NSString *urlString = [[NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&backScheme=%@&sname=我的位置&dlat=%lf&dlon=%lf&dname=%@&dev=0&style=2&m=0&t=0",tempAppName,tempUrlScheme,destinationMode.destinationLatitude.floatValue,destinationMode.destinationLongitude.floatValue,destinationMode.destinationName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}

/**
 * 腾讯地图路线规划
 * 文档:http://lbs.qq.com/uri_v1/guide-route.html
 */
- (void)doQQNavigation {
    NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
    NSString *tempAppName = [NSString stringWithFormat:@"%@",infoDic[@"CFBundleDisplayName"]];
    NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?type=drive&from=我的位置&to=%@&tocoord=%f,%f&coord_type=1&policy=0&refer=%@",destinationMode.destinationName,   destinationMode.destinationLatitude.floatValue, destinationMode.destinationLongitude.floatValue, tempAppName] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}

/**
 * 谷歌地图路线规划
 * 文档:https://developers.google.com/maps/documentation/ios/urlscheme
 */
- (void)doGoogleNavigation {
    NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
    NSString *tempAppName = [NSString stringWithFormat:@"%@",infoDic[@"CFBundleDisplayName"]];
    NSString *tempUrlScheme = @"demoURL://";
    NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving", tempAppName, tempUrlScheme, destinationMode.destinationLatitude.floatValue, destinationMode.destinationLongitude.floatValue] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}

@end

[Swift]

    // 到这去
    func turnAction(_ sender: Any) {
        guard let topVC = ScreenUIManager.topViewController() else {
            return
        }
        var tempMsg = "导航到店铺的位置"
        let tempName = shopModel?.shopName ?? "店铺"
        if shopModel?.shopName != "" {
            tempMsg = "导航到“\(tempName)”的位置"
        }
        let alert = UIAlertController(title: nil, message: tempMsg, preferredStyle: .actionSheet)
        
        if let tempURL = URL(string: "http://maps.apple.com/") , UIApplication.shared.canOpenURL(tempURL) {
            let appleMapAction = UIAlertAction(title: "苹果地图", style: .default) { [weak self] action in
                self?.doAppleNavigation()
            }
            alert.addAction(appleMapAction)
        }
        
        if let tempURL = URL(string: "baidumap://") , UIApplication.shared.canOpenURL(tempURL) {
            let baiduMapAction = UIAlertAction(title: "百度地图", style: .default) { [weak self] action in
                self?.doBaiduNavigation()
            }
            alert.addAction(baiduMapAction)
        }

        if let tempURL = URL(string: "iosamap://") , UIApplication.shared.canOpenURL(tempURL) {
            let gaodeMapAction = UIAlertAction(title: "高德地图", style: .default) { [weak self] action in
                self?.doGaodeNavigation()
            }
            alert.addAction(gaodeMapAction)
        }

        if let tempURL = URL(string: "qqmap://") , UIApplication.shared.canOpenURL(tempURL) {
            let gaodeMapAction = UIAlertAction(title: "腾讯地图", style: .default) { [weak self] action in
                self?.doQQNavigation()
            }
            alert.addAction(gaodeMapAction)
        }
        
        if let tempURL = URL(string: "comgooglemaps://") , UIApplication.shared.canOpenURL(tempURL) {
            let googleMapAction = UIAlertAction(title: "谷歌地图", style: .default) { [weak self] action in
                self?.doGoogleNavigation()
            }
            alert.addAction(googleMapAction)
        }
     
        let cancelAction = UIAlertAction(title: "取消", style: .cancel) { action in
        
        }
        alert.addAction(cancelAction)
        topVC.present(alert, animated: true, completion: nil)
    }
     
    func fromCoordinate() -> CLLocationCoordinate2D {
        let tempLatitude = AppUserDefaults.shared.latitude ?? ""
        let tempLongitude = AppUserDefaults.shared.longitude ?? ""
        let fromCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(CLLocationDegrees(tempLatitude.toFloat() ?? 0.0), CLLocationDegrees(tempLongitude.toFloat() ?? 0.0))
        return fromCoordinate
    }
    
    func toCoordinate() -> CLLocationCoordinate2D {
        let tempLatitude = shopModel?.latitude ?? ""
        let tempLongitude = shopModel?.longitude ?? ""
        let toCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(CLLocationDegrees(tempLatitude.toFloat() ?? 0.0), CLLocationDegrees(tempLongitude.toFloat() ?? 0.0))
        return toCoordinate
    }
    
    /**
     * 苹果地图路线规划
     * 文档:https://developer.apple.com/documentation/mapkit/mkmapitem
     */
    func doAppleNavigation() {
        let fromCoordinate = fromCoordinate()
        let toCoordinate = toCoordinate()
        let fromPlacemark: MKPlacemark = MKPlacemark(coordinate: fromCoordinate, addressDictionary: nil)
        let toPlacemark: MKPlacemark = MKPlacemark(coordinate: toCoordinate, addressDictionary: nil)
        let fromItem: MKMapItem = MKMapItem(placemark: fromPlacemark)
        fromItem.name = "我的位置"
        let toItem: MKMapItem = MKMapItem(placemark: toPlacemark)
        toItem.name = shopModel?.shopName
        MKMapItem.openMaps(with: [fromItem,toItem], launchOptions: [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsShowsTrafficKey: NSNumber(value: true)])
    }
     
    /**
     * 百度地图路线规划
     * 文档:http://lbsyun.baidu.com/index.php?title=uri/api/ios
     */
    func doBaiduNavigation() {
        let toCoordinate = toCoordinate()
        var urlString = "baidumap://map/direction?origin={{我的位置}}&destination=name:\(shopModel?.shopName ?? "")|latlng:\(toCoordinate.latitude),\(toCoordinate.longitude)&mode=driving&coord_type=gcj02"
        urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
        
        guard let tempURL: URL = NSURL(string: urlString) as URL? else {
            return
        }
        if UIApplication.shared.canOpenURL(tempURL) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(tempURL, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(tempURL)
            }
        }
    }
     
    /**
     * 高德地图路线规划
     * 文档:http://lbs.amap.com/api/amap-mobile/guide/ios/route
     */
    func doGaodeNavigation() {
        let infoDict = Bundle.main.infoDictionary
        let tempAppName = "\(String(describing: infoDict?["CFBundleDisplayName"]))"
        let tempUrlScheme = "demoURL://";
        let toCoordinate = toCoordinate()
        var urlString = "iosamap://path?sourceApplication=\(tempAppName)&backScheme=\(tempUrlScheme)&sname=我的位置&dlat=\(toCoordinate.latitude)&dlon=\(toCoordinate.longitude)&dname=\(String(describing: shopModel?.shopName))&dev=0&style=2&m=0&t=0"
        urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!

        guard let tempURL: URL = NSURL(string: urlString) as URL? else {
            return
        }
        if UIApplication.shared.canOpenURL(tempURL) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(tempURL, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(tempURL)
            }
        }
    }
     
    /**
     * 腾讯地图路线规划
     * 文档:http://lbs.qq.com/uri_v1/guide-route.html
     */
    func doQQNavigation() {
        let infoDict = Bundle.main.infoDictionary
        let tempAppName = "\(String(describing: infoDict?["CFBundleDisplayName"]))"
        let toCoordinate = toCoordinate()
        var urlString = "qqmap://map/routeplan?type=drive&from=我的位置&to=\(String(describing: shopModel?.shopName))&tocoord=\(toCoordinate.latitude),\(toCoordinate.longitude)&coord_type=1&policy=0&refer=\(tempAppName)"
        urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
        
        guard let tempURL: URL = NSURL(string: urlString) as URL? else {
            return
        }
        if UIApplication.shared.canOpenURL(tempURL) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(tempURL, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(tempURL)
            }
        }
    }
     
    /**
     * 谷歌地图路线规划
     * 文档:https://developers.google.com/maps/documentation/ios/urlscheme
     */
    func doGoogleNavigation() {
        let infoDict = Bundle.main.infoDictionary
        let tempAppName = "\(String(describing: infoDict?["CFBundleDisplayName"]))"
        let tempUrlScheme = "demoURL://"
        let toCoordinate = toCoordinate()
        var urlString = "comgooglemaps://?x-source=\(tempAppName)&x-success=\(tempUrlScheme)&saddr=&daddr=\(toCoordinate.latitude),\(toCoordinate.longitude)&directionsmode=driving"
        urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!

        guard let tempURL: URL = NSURL(string: urlString) as URL? else {
            return
        }
        if UIApplication.shared.canOpenURL(tempURL) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(tempURL, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(tempURL)
            }
        }
    }

TO:

iOS开发:采用URI方式跳转到各类地图进行导航

iOS9AdaptationTips

iOS开发—跳转方式实现地图导航功能

URI跳转方式地图导航的代码实践

示意图:

各地图APP路线规划如下:

苹果地图

高德地图

百度地图

腾讯地图

谷歌地图  翻墙后才有展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值