[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:
示意图:
各地图APP路线规划如下:
苹果地图
高德地图
百度地图
腾讯地图
谷歌地图 翻墙后才有展示