我有一个集成了地图套件的视图控制器。我需要在打开地图之前拍摄警报,要求从地图的所有类似应用中进行选择以打开它。例如,如果谷歌地图应用程序安装在我的iPhone中,则应该有一个选项,以及默认的mapkit视图。是否有可能实现此功能,从iphone扫描每个类似的应用程序并返回结果作为打开地图的选项。
答案 0 :(得分:25)
您可以使用sumesh的回答[1]创建一系列检查以映射已安装的应用:
var installedNavigationApps : [String] = ["Apple Maps"] // Apple Maps is always installed
您可以想到的每个导航应用程序:
if (UIApplication.sharedApplication().canOpenURL(url: NSURL)) {
self.installedNavigationApps.append(url)
} else {
// do nothing
}
常见的导航应用是:
可以在http://wiki.akosma.com/IPhone_URL_Schemes
找到更多内容创建已安装的导航应用程序列表后,您可以呈现UIAlertController:
let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .ActionSheet)
for app in self.installNavigationApps {
let button = UIAlertAction(title: app, style: .Default, handler: nil)
alert.addAction(button)
}
self.presentViewController(alert, animated: true, completion: nil)
当然,您需要使用指定的urlscheme在处理程序中添加按钮单击的行为。例如,如果单击Google地图,请使用以下内容:
UIApplication.sharedApplication().openURL(NSURL(string:
"comgooglemaps://?saddr=&daddr=\(place.latitude),\(place.longitude)&directionsmode=driving")!) // Also from sumesh's answer
只安装了Apple地图和Google地图,这将产生如下内容:
答案 1 :(得分:10)
快速5 +
基于@Emptyless答案。
import MapKit
func openMapButtonAction() {
let latitude = 45.5088
let longitude = -73.554
let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"
let googleItem = ("Google Map", URL(string:googleURL)!)
let wazeItem = ("Waze", URL(string:wazeURL)!)
var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]
if UIApplication.shared.canOpenURL(googleItem.1) {
installedNavigationApps.append(googleItem)
}
if UIApplication.shared.canOpenURL(wazeItem.1) {
installedNavigationApps.append(wazeItem)
}
let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .actionSheet)
for app in installedNavigationApps {
let button = UIAlertAction(title: app.0, style: .default, handler: { _ in
UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
})
alert.addAction(button)
}
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(cancel)
present(alert, animated: true)
}
也将它们放在您的info.plist中:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
干杯!
答案 2 :(得分:6)
基于先前答案的Swift 5+解决方案,该解决方案显示了 Apple Maps,Google Maps,Waze和City Mapper 之间的选择器。它还允许使用可选位置标题(对于支持该功能的应用程序),并且仅在选项多于1个时显示警报(如果只有1个选项,它将自动打开或不执行任何操作)。
func openMaps(latitude: Double, longitude: Double, title: String?) {
let application = UIApplication.shared
let coordinate = "\(latitude),\(longitude)"
let encodedTitle = title?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let handlers = [
("Apple Maps", "http://maps.apple.com/?q=\(encodedTitle)&ll=\(coordinate)"),
("Google Maps", "comgooglemaps://?q=\(coordinate)"),
("Waze", "waze://?ll=\(coordinate)"),
("Citymapper", "citymapper://directions?endcoord=\(coordinate)&endname=\(encodedTitle)")
]
.compactMap { (name, address) in URL(string: address).map { (name, $0) } }
.filter { (_, url) in application.canOpenURL(url) }
guard handlers.count > 1 else {
if let (_, url) = handlers.first {
application.open(url, options: [:])
}
return
}
let alert = UIAlertController(title: R.string.localizable.select_map_app(), message: nil, preferredStyle: .actionSheet)
handlers.forEach { (name, url) in
alert.addAction(UIAlertAction(title: name, style: .default) { _ in
application.open(url, options: [:])
})
}
alert.addAction(UIAlertAction(title: R.string.localizable.cancel(), style: .cancel, handler: nil))
contextProvider.currentViewController.present(alert, animated: true, completion: nil)
}
请注意,此解决方案使用R.swift进行字符串本地化,但是您可以正常地将其替换为NSLocalizedString
,并使用contextProvider.currentViewController
来获得显示的UIViewController
,但是您可以如果您已经在视图控制器中调用它,则将其替换为self
。
与往常一样,您还需要将以下内容添加到您的应用程序Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>citymapper</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
答案 3 :(得分:3)
基于@Angel G. Olloqui 的 SwiftUI 方法回答:
<块引用>struct YourView: View {
@State private var showingSheet = false
var body: some View {
VStack {
Button(action: {
showingSheet = true
}) {
Text("Navigate")
}
}
.actionSheet(isPresented: $showingSheet) {
let latitude = 45.5088
let longitude = -73.554
let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"
let googleItem = ("Google Map", URL(string:googleURL)!)
let wazeItem = ("Waze", URL(string:wazeURL)!)
var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]
if UIApplication.shared.canOpenURL(googleItem.1) {
installedNavigationApps.append(googleItem)
}
if UIApplication.shared.canOpenURL(wazeItem.1) {
installedNavigationApps.append(wazeItem)
}
var buttons: [ActionSheet.Button] = []
for app in installedNavigationApps {
let button: ActionSheet.Button = .default(Text(app.0)) {
UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
}
buttons.append(button)
}
let cancel: ActionSheet.Button = .cancel()
buttons.append(cancel)
return ActionSheet(title: Text("Navigate"), message: Text("Select an app..."), buttons: buttons)
}
}
}
另外,将以下内容添加到您的 Info.plist
<块引用><key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
答案 4 :(得分:0)
对于任何寻求类似东西的人 现在,您可以使用UIActivityViewController,与单击共享按钮时使用的UIControl Photos或Safari相同。
对于苹果地图和谷歌地图,您可以添加自定义应用程序活动以与其他项目一起显示。您需要子类化UIActivity并覆盖title和image方法。然后perform()函数可以处理自定义项目上的点击
下面是我为此编写的目标C代码。 对于Swift代码,您可以参考UIActivityViewController swift
NSMutableArray *activityArray = [[NSMutableArray alloc] init];
// Check if google maps is installed and accordingly add it in menu
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
GoogleMapsActivityView *googleMapsActivity = [[GoogleMapsActivityView alloc] init];
[activityArray addObject:googleMapsActivity];
}
// Check if apple maps is installed and accordingly add it in menu
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"maps://"]]) {
AppleMapsActivityView *appleMapsActivity = [[AppleMapsActivityView alloc] init];
[activityArray addObject:appleMapsActivity];
}
NSArray *currentPlaces = [NSArray arrayWithObject:place];
UIActivityViewController *activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:currentPlaces
applicationActivities:activityArray];
activityViewController.excludedActivityTypes = @[UIActivityTypePrint,
UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypePostToWeibo,
UIActivityTypeAddToReadingList,
UIActivityTypePostToVimeo,
UIActivityTypeAirDrop];
[self presentViewController:activityViewController animated:YES completion:nil];
并继承GoogleMapsActivity
@interface GoogleMapsActivityView: UIActivity
@end
@implementation GoogleMapsActivityView
- (NSString *)activityType {
return @"yourApp.openplace.googlemaps";
}
- (NSString *)activityTitle {
return NSLocalizedString(@"Open with Google Maps", @"Activity view title");
}
- (UIImage *)activityImage {
return [UIImage imageNamed:@"ic_google_maps_logo"];
}
- (UIActivityCategory)activityCategory {
return UIActivityCategoryAction;
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
return YES;
}
- (void)performActivity {
CLLocationDegrees lat = 99999;
CLLocationDegrees lng = 99999;
NSString *latlong = [NSString stringWithFormat:@"%.7f,%@%.7f", lat, @"", lng];
NSString *urlString = [NSString stringWithFormat:@"comgooglemaps://?q=%@", latlong];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]
options:@{}
completionHandler:nil];
}
[self activityDidFinish:YES];
}