I'm trying to incorporate a feature in my app that will give the user walking directions to a location via MapKit. I've seen it on the Maps app but I don't know how to do it myself. I got directions for a car but am stumped on how to do it for walking. This is what I have so far:
func getDirections(){
let request = MKDirectionsRequest()
request.source = MKMapItem.mapItemForCurrentLocation()
request.destination = destination
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response, error) in
if error != nil {
print("Error \(error)")
} else {
//self.dispLayRout(response)
var overlays = self.mapView.overlays
self.mapView.removeOverlays(overlays)
for route in response!.routes as! [MKRoute] {
self.mapView.addOverlay(route.polyline,
level: MKOverlayLevel.AboveRoads)
var instructionNumber = 0
for next in route.steps {
instructionNumber += 1
print(next.instructions)
}
}
}
}
Also I don't want it to have to open the Maps app up. I need it to find the route inside my app.
MKDirectionsRequest has a transportType property. Add this right after you create your transport request:
let request = MKDirectionsRequest()
request.transportType = .Walking
(I've never tried to get walking directions before, but I found that in the Xcode docs in less than 30 seconds. Learn your way around the Xcode "Documentation and API reference" in the help menu. It contains a wealth of information.)
Related
Followed a video tutorial. When i build this app and hit the directions button it takes me to a random area instead of the coordinates provided. I am a beginner. Also, is there a way to pass in the locations address instead of coordinates, or should i just use the coordinates. Thanks for any responses. I am using Swift 5 in xCode 10. I changed the coordinate for privacy.
#IBAction func directionsClinic(_ sender: UIButton) {
let latitude:CLLocationDegrees = 38.465492
let longitude:CLLocationDegrees = 91.338905
let regionDistance:CLLocationDistance = 1000;
let coordinates = CLLocationCoordinate2DMake(latitude,
longitude)
let regionSpan = MKCoordinateRegion(center: coordinates,
latitudinalMeters: regionDistance, longitudinalMeters:
regionDistance)
let options = [MKLaunchOptionsMapCenterKey:
NSValue(mkCoordinate:regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan:
regionSpan.span)]
let placemark = MKPlacemark(coordinate: coordinates)
let mapItem = MKMapItem(placemark:placemark)
mapItem.openInMaps(launchOptions: options)
}
i have just tried a few different youtube videos guides, but most were a year+ old and im not sure if the code has changed
Expected the location of the coordinates to show up in the native iphone maps app, instead it was taking me to a place on the other side of the globe.
You can try this to open with a specific address:
let baseUrl: String = "http://maps.apple.com/?q="
let encodedName = theAddress.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed) ?? ""
let finalUrl = baseUrl + encodedName
if let url = NSURL(string: finalUrl) {
UIApplication.shared.open(url)
}
The Maps app will intercept the request and open the app.
I m working on application like Uber and Careem. When user searches for a location using Google Places Autocomplete API, I want to show the distance as well along with the name of the autocomplete resulted place like Uber and Careem does this.
Plz have a look on this image for further clarification
Edit:
where cuGMS is array of GMSAutocompletePrediction
let cuGMS = self.resultsArray[indexPath.row]
let placesClient = GMSPlacesClient()
placesClient.lookUpPlaceID(cuGMS.placeID!, callback: { (response , error) in
print("response \(response)")
if(error == nil)
{
let coor = response?.coordinate
let lat = coor?.latitude
let lon = coor?.longitude
}
else
{
}
})
try this
let loc1:CLLocation = CLLocation.init(latitude: 30.0000, longitude:29.2545)
let loc2:CLLocation = CLLocation.init(latitude: 28.02002, longitude:27.00021)
let dis = loc1.distance(from: loc2)
I have searched the internet but couldn't find if I can get the map image from the latitude and logitude.
Is there any api which can give me the map image .
Because I got start location and end location.
When I give the start and end location , it should give me map image with route .
Is the possible .
If I am on mapview I can manage snapshot , but here I won't have any mapview.
Any links, ideas , suggestions highly appreciated.
Regards.
I don´t know if there are any API´s available for this, but when I do this I just call the Apple Maps app and provide a latitude and longitude for my position and open up that app.
In that way the user can use the Apple Maps application to navigate and get full information about roads etc.
Here is how I call this:
func navigateWithAppleMaps(latitude: Double, longitude: Double) {
let regionDistance:CLLocationDistance = 10000
let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)
let options = [
MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "Start"
mapItem.openInMaps(launchOptions: options)
}
I think you have to use google developer static map api for this
https://developers.google.com/maps/documentation/static-maps/intro
You can get image from just passing latitude and longitude from following code. You can set zoom on mapview in URL.
var staticMapUrl: String = "http://maps.google.com/maps/api/staticmap?markers=color:red|\(YOUR LATITUDE HERE),\(YOUR LONGITUDE HERE)&\("zoom=16&size=400x400")&sensor=true"
var mapUrl = URL(string: staticMapUrl.addingPercentEscapes(using: String.Encoding.utf8))
var image = UIImage(data: Data(contentsOf: mapUrl))
SWIFT 5 creating two pins on map and path between them
Lets first get path between 2 points using google api:
//=== get points ===
var encodedPathPoints = "" //we'll get this from google api
let pointsUrl = "https://maps.googleapis.com/maps/api/directions/json?origin=\(location1.lat!),\(location1.long!)&destination=\(location2.lat!),\(location2.long!)&sensor=false&mode=driving&key=\(ServiceConstants.MAP_KEY)"
if Reachability.isConnectedToNetwork(){
AF.request(pointsUrl).responseJSON { response in
let json = try? JSON(data: response.data!)
if json != nil {
print("JSON map results: \(json)")
let routes = json!["routes"].arrayValue
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
let points = routeOverviewPolyline?["points"]?.stringValue
if points != nil {
encodedPathPoints = points!
}
}
}
}
}
Once i have path between my two points let set static map image
let MAP_BASE_URL = "https://maps.googleapis.com/maps/api/staticmap?"
let MAP_IMAGE_SIZE = "size=\(2 * Int(imageView.frame.size.width))x\(2 * Int(imageView.frame.size.height))"
let MAP_MARKER = "&markers=icon:https://www.google.com|";//your icon url
let MAP_deliveryLocation = "\(location.lat!),\(location.long!)"
let MAP_WAYPOINT = "\(storeLocation.lat!),\(storeLocation.long!)"
let MAP_KEY = "&key=\(ServiceConstants.MAP_KEY)"
let MAP_STYLE = "&format=png&maptype=roadmap&style=element:geometry|color:0xf5f5f5&style=element:labels.icon|visibility:off&style=element:labels.text.fill|color:0x616161&style=element:labels.text.stroke|color:0xf5f5f5&style=feature:administrative.land_parcel|element:labels.text.fill|color:0xbdbdbd&style=feature:poi|element:geometry|color:0xeeeeee&style=feature:poi|element:labels.text.fill|color:0x757575&style=feature:poi.park|element:geometry|color:0xe5e5e5&style=feature:poi.park|element:labels.text.fill|color:0x9e9e9e&style=feature:road|element:geometry|color:0xffffff&style=feature:road.arterial|element:labels.text.fill|color:0x757575&style=feature:road.highway|element:geometry|color:0xdadada&style=feature:road.highway|element:labels.text.fill|color:0x616161&style=feature:road.local|element:labels.text.fill|color:0x9e9e9e&style=feature:transit.line|element:geometry|color:0xe5e5e5&style=feature:transit.station|element:geometry|color:0xeeeeee&style=feature:water|element:geometry|color:0xc9c9c9&style=feature:water|element:labels.text.fill|color:0x9e9e9e&size=480x360"
let PATH = "&path=color:0x11C856|weight:5|enc:\(encodedPathPoints)" //use 'enc:' if you're using encoded path just like me, you can ignore this if you're using normal lat lng points concatenated in string.
let mapStaticImgUrlStr = "\(MAP_BASE_URL)\(MAP_IMAGE_SIZE)\(PATH)¢er=\(MAP_deliveryLocation)|\(MAP_WAYPOINT)\(MAP_MARKER)\(MAP_deliveryLocation)\(MAP_MARKER)\(MAP_WAYPOINT)\(MAP_STYLE)\(MAP_KEY)"
let url = URL(string: mapStaticImgUrlStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
do {
let data = try NSData(contentsOf: url3!, options: NSData.ReadingOptions())
imageView.image = UIImage(data: data as Data)
} catch {
imageView.image = UIImage()
}
I want to open the Apple Maps App in my own Swift App, but I have only zipcode, city & street. I have NO Coordinates. I researched a lot, but there were only ways with using coordination information.
You can just pass your address information as URL parameters in the URL with which you open the maps app. Say you wanted the maps app to open centered on The White House.
UIApplication.sharedApplication().openURL(NSURL(string: "http://maps.apple.com/?address=1600,PennsylvaniaAve.,20500")!)
The Maps app opens with the ugly query string in the search field but it shows the right location. Note that the city and state are absent from the search query, it's just the street address and the zip.
A potentially better approach, depending on your needs, would be to get the CLLocation of the address info you have using CLGeocoder.
let geocoder = CLGeocoder()
let str = "1600 Pennsylvania Ave. 20500" // A string of the address info you already have
geocoder.geocodeAddressString(str) { (placemarksOptional, error) -> Void in
if let placemarks = placemarksOptional {
print("placemark| \(placemarks.first)")
if let location = placemarks.first?.location {
let query = "?ll=\(location.coordinate.latitude),\(location.coordinate.longitude)"
let path = "http://maps.apple.com/" + query
if let url = NSURL(string: path) {
UIApplication.sharedApplication().openURL(url)
} else {
// Could not construct url. Handle error.
}
} else {
// Could not get a location from the geocode request. Handle error.
}
} else {
// Didn't get any placemarks. Handle error.
}
}
Swift 4 and above
Use this version to get the coordinates for the Address, there is also a way to open it directly with the address, but that is susceptible to errors
import CoreLocation
let myAddress = "One,Apple+Park+Way,Cupertino,CA,95014,USA"
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(myAddress) { (placemarks, error) in
guard let placemarks = placemarks?.first else { return }
let location = placemarks.location?.coordinate ?? CLLocationCoordinate2D()
guard let url = URL(string:"http://maps.apple.com/?daddr=\(location.latitude),\(location.longitude)") else { return }
UIApplication.shared.open(url)
}
Apple has a Documentation about the Map URL Scheme. Look here: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html#//apple_ref/doc/uid/TP40007899-CH5-SW1
Using Swift 4 and Xcode 9
At the top:
import CoreLocation
Then:
let geocoder = CLGeocoder()
let locationString = "London"
geocoder.geocodeAddressString(locationString) { (placemarks, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let location = placemarks?.first?.location {
let query = "?ll=\(location.coordinate.latitude),\(location.coordinate.longitude)"
let urlString = "http://maps.apple.com/".appending(query)
if let url = URL(string: urlString) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}
}
Swift 5: Directly open maps app
///Opens text address in maps
static func openAddressInMap(address: String?){
guard let address = address else {return}
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(address) { (placemarks, error) in
guard let placemarks = placemarks?.first else {
return
}
let location = placemarks.location?.coordinate
if let lat = location?.latitude, let lon = location?.longitude{
let destination = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: lat, longitude: lon)))
destination.name = address
MKMapItem.openMaps(
with: [destination]
)
}
}
}
I want to draw route on Map without using google API.
I am tracking the user with co-ordinates of user. So i draw polylines to show user route,but now my client wants to remove those polylines and want to show routes like google have. Is it possible in which i can pass all co-ordinates route map drawn on those co-ordinates?
Actually you can use MKDirections built-in MapKit Framework. here's the further information: https://developer.apple.com/library/mac/documentation/MapKit/Reference/MKDirections_class/.
Show you some snippet which is calculating the route of two locations:
func caculateDirections(fromCoordinate: CLLocationCoordinate2D, toCoordinate: CLLocationCoordinate2D) {
let from = MKMapItem(placemark: MKPlacemark(coordinate: fromCoordinate, addressDictionary: nil))
let to = MKMapItem(placemark: MKPlacemark(coordinate: toCoordinate, addressDictionary: nil))
let request = MKDirectionsRequest()
request.source = from
request.destination = to
request.transportType = .Automobile
let directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response, error) -> Void in
if let response = response {
// Here you can get the routes and draw it on the map
let routes = response.routes
} else {
print("Error:\(error?.description)")
}
}
}
You can learn more from this tutorial: http://www.devfright.com/mkdirections-tutorial/