Previous to iOS 6, opening a URL like this would open the (Google) Maps app:
NSURL *url = [NSURL URLWithString:@"http://maps.google.com/?q=New+York"];
[[UIApplication sharedApplication] openURL:url];
Now with the new Apple Maps implementation, this just opens Mobile Safari to Google Maps. How can I accomplish the same behavior with iOS 6? How do I programmatically open the Maps app and have it point to a specific location/address/search/whatever?
Here's the official Apple way:
// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)])
{
// Create an MKMapItem to pass to the Maps app
CLLocationCoordinate2D coordinate =
CLLocationCoordinate2DMake(16.775, -3.009);
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate
addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:@"My Place"];
// Pass the map item to the Maps app
[mapItem openInMapsWithLaunchOptions:nil];
}
If you want to get driving or walking instructions to the location, you can include a mapItemForCurrentLocation
with the MKMapItem
in the array in +openMapsWithItems:launchOptions:
, and set the launch options appropriately.
// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)])
{
// Create an MKMapItem to pass to the Maps app
CLLocationCoordinate2D coordinate =
CLLocationCoordinate2DMake(16.775, -3.009);
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate
addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:@"My Place"];
// Set the directions mode to "Walking"
// Can use MKLaunchOptionsDirectionsModeDriving instead
NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeWalking};
// Get the "Current User Location" MKMapItem
MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
// Pass the current location and destination map items to the Maps app
// Set the direction mode in the launchOptions dictionary
[MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem]
launchOptions:launchOptions];
}
You can preserve your original iOS 5 and lower code in an else
statement after that if
. Note that if you reverse the order of items in the openMapsWithItems:
array, you'll get directions from the coordinate to your current location. You could probably use it to get directions between any two locations by passing a constructed MKMapItem
instead of the current location map item. I haven't tried that.
Finally, if you have an address (as a string) that you want directions to, use the geocoder to create an MKPlacemark
, by way of CLPlacemark
.
// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)])
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:@"Piccadilly Circus, London, UK"
completionHandler:^(NSArray *placemarks, NSError *error) {
// Convert the CLPlacemark to an MKPlacemark
// Note: There's no error checking for a failed geocode
CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc]
initWithCoordinate:geocodedPlacemark.location.coordinate
addressDictionary:geocodedPlacemark.addressDictionary];
// Create a map item for the geocoded address to pass to Maps app
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:geocodedPlacemark.name];
// Set the directions mode to "Driving"
// Can use MKLaunchOptionsDirectionsModeWalking instead
NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
// Pass the current location and destination map items to the Maps app
// Set the direction mode in the launchOptions dictionary
[MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem] launchOptions:launchOptions];
}];
}
Found the answer to my own question. Apple documents its maps URL format here. It looks like you can essentially replace maps.google.com
with maps.apple.com
.
Update: It turns out that the same is true in MobileSafari on iOS 6; tapping a link to http://maps.apple.com/?q=...
opens the Maps app with that search, the same way http://maps.google.com/?q=...
did on previous versions. This works and is documented in the page linked above.
UPDATE: This answers my question relating to the URL format. But nevan king's answer here (see below) is an excellent summary of the actual Maps API.
The best way to do it is to call new iOS 6 method on MKMapItem
openInMapsWithLaunchOptions:launchOptions
Example:
CLLocationCoordinate2D endingCoord = CLLocationCoordinate2DMake(40.446947, -102.047607);
MKPlacemark *endLocation = [[MKPlacemark alloc] initWithCoordinate:endingCoord addressDictionary:nil];
MKMapItem *endingItem = [[MKMapItem alloc] initWithPlacemark:endLocation];
NSMutableDictionary *launchOptions = [[NSMutableDictionary alloc] init];
[launchOptions setObject:MKLaunchOptionsDirectionsModeDriving forKey:MKLaunchOptionsDirectionsModeKey];
[endingItem openInMapsWithLaunchOptions:launchOptions];
This will start the navigation for driving from the current location.
I see you found the maps.apple.com url "scheme". It's a good choice because it will automatically redirect older devices to maps.google.com. But for iOS 6 there is a new class you might want to take advantage of: MKMapItem.
Two methods that are of interest to you:
- -openInMapsWithLaunchOptions: - call it on an MKMapItem instance to open it in Maps.app
- +openMapsWithItems:launchOptions: - call it on MKMapItem class to open an array of MKMapItem instances.
Here is a class using nevan king's solution completed in Swift:
class func openMapWithCoordinates(theLon:String, theLat:String){
var coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(theLon), CLLocationDegrees(theLat))
var placemark:MKPlacemark = MKPlacemark(coordinate: coordinate, addressDictionary:nil)
var mapItem:MKMapItem = MKMapItem(placemark: placemark)
mapItem.name = "Target location"
let launchOptions:NSDictionary = NSDictionary(object: MKLaunchOptionsDirectionsModeDriving, forKey: MKLaunchOptionsDirectionsModeKey)
var currentLocationMapItem:MKMapItem = MKMapItem.mapItemForCurrentLocation()
MKMapItem.openMapsWithItems([currentLocationMapItem, mapItem], launchOptions: launchOptions)
}
I found it annoying that using the http://maps.apple.com?q=... link setup opens the safari browser first at older devices.
So for an iOS 5 device opening up your app with a reference to maps.apple.com the steps look like:
- you click something in the app and it refers to the maps.apple.com url
- safari opens up the link
- the maps.apple.com server redirects to the maps.google.com url
- the maps.google.com url gets interpreted and opens the google Maps app.
I think that the (very obvious and confusing) steps 2 and 3 are annoying to users. Therefore i check the os version and either run maps.google.com or maps.apple.com on the device (for resp. ios 5 or ios 6 OS versions).
My research on this issue lead me to the following conclusions:
- If you use maps.google.com then it will open the map in safari for every ios.
- If you use maps.apple.com then it will open the map in map application of ios 6 and also work greate with ios 5 and in ios 5 it open the map as normal in safari.
If you want to open Google Maps instead (or offer as a secondary option), you can use the comgooglemaps://
and comgooglemaps-x-callback://
URL schemes documented here.
Before launching url, remove any special character from the url and replace spaces by +. This will save you some headaches:
NSString *mapURLStr = [NSString stringWithFormat: @"http://maps.apple.com/?q=%@",@"Limmattalstrasse 170, 8049 Zürich"];
mapURLStr = [mapURLStr stringByReplacingOccurrencesOfString:@" " withString:@"+"];
NSURL *url = [NSURL URLWithString:[mapURLStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
if ([[UIApplication sharedApplication] canOpenURL:url]){
[[UIApplication sharedApplication] openURL:url];
}
NSString *address = [NSString stringWithFormat:@"%@ %@ %@ %@"
,[dataDictionary objectForKey:@"practice_address"]
,[dataDictionary objectForKey:@"practice_city"]
,[dataDictionary objectForKey:@"practice_state"]
,[dataDictionary objectForKey:@"practice_zipcode"]];
NSString *mapAddress = [@"http://maps.apple.com/?q=" stringByAppendingString:[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"Map Address %@",mapAddress);
[objSpineCustomProtocol setUserDefaults:mapAddress :@"webSiteToLoad"];
[self performSegueWithIdentifier: @"provider_to_web_loader_segue" sender: self];
//VKJ
Updated to Swift 4 based on @PJeremyMalouf's answer:
private func navigateUsingAppleMaps(to coords:CLLocation, locationName: String? = nil) {
let placemark = MKPlacemark(coordinate: coords.coordinate, addressDictionary:nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = locationName
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
let currentLocationMapItem = MKMapItem.forCurrentLocation()
MKMapItem.openMaps(with: [currentLocationMapItem, mapItem], launchOptions: launchOptions)
}
Not using maps, just programmatically using a UiButton action, this worked great for me.
// Button triggers the map to be presented.
@IBAction func toMapButton(sender: AnyObject) {
//Empty container for the value
var addressToLinkTo = ""
//Fill the container with an address
self.addressToLinkTo = "http://maps.apple.com/?q=111 Some place drive, Oak Ridge TN 37830"
self.addressToLinkTo = self.addressToLinkTo.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
let url = NSURL(string: self.addressToLinkTo)
UIApplication.sharedApplication().openURL(url!)
}
You could spread some of this code out a bit. For example, I put the variable as a class level variable, had another function fill it, and then when pressed the button simply took what was in the variable and scrubbed it to be used in a URL.
来源:https://stackoverflow.com/questions/12504294/programmatically-open-maps-app-in-ios-6