I have 2 locations in the map. First one is users current location with blue dot placemark and the second one is specified restaurant location near of the users current location with red dot placemark. I want to get directions from user's current location to restaurant location. I am getting directions when I define latitude and longitude values like latitude: 38.00001 and longitude: 27.08980.
Also I am getting each restaurants location from api to red dot placemark but do not get directions from user current location to restaurant location.
I am getting restaurant location with these codes:
var viewModel: DetailsViewModel? {
didSet {
updateView()
}
willSet {
updateView()
}
}
func updateView() {
if let viewModel = viewModel {
detailsFoodView?.priceLabel?.text = viewModel.price
detailsFoodView?.hoursLabel?.text = viewModel.isOpen
detailsFoodView?.locationLabel?.text = viewModel.phoneNumber
detailsFoodView?.ratingsLabel?.text = viewModel.rating
detailsFoodView?.collectionView?.reloadData()
centerMap(for: viewModel.coordinate)
print("detail restaurant destination : \(viewModel.coordinate)")
title = viewModel.name
print("title: \(title)")
}
}
func centerMap(for coordinate: CLLocationCoordinate2D) {
let region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 100, longitudinalMeters: 100)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
detailsFoodView?.mapView?.addAnnotation(annotation)
detailsFoodView?.mapView?.setRegion(region, animated: true)
}
}
And in viewDidLoad() getting directions like:
let sourceCoordinates = locationManager.location?.coordinate
Problem is here
I do not get each restaurant's latitude and longitude values to destCoordinates. Normally, I get with viewModel.coordinate.
But if I use
let destCoordinates = CLLocationCoordinate2D(latitude: viewModel?.coordinate.latitude, longitude: viewModel?.coordinate.longitude)
Instead of:
let destCoordinates = CLLocationCoordinate2D(latitude: 38.420183, longitude: 27.205559)
I am getting latitude and longitude values nil or zero.
let sourcePlaceMark = MKPlacemark(coordinate: sourceCoordinates!)
let destPlaceMark = MKPlacemark(coordinate: destCoordinates)
let sourceItem = MKMapItem(placemark: sourcePlaceMark)
let destItem = MKMapItem(placemark: destPlaceMark)
let directionRequest = MKDirections.Request()
directionRequest.source = sourceItem
directionRequest.destination = destItem
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate(completionHandler: {response, error in
guard let response = response else {
if error != nil {
print("Something went wrong!")
}
return
}
let route = response.routes[0]
self.detailsFoodView?.mapView?.addOverlay(route.polyline, level: .aboveRoads)
let rect = route.polyline.boundingMapRect
self.detailsFoodView?.mapView?.setRegion(MKCoordinateRegion(rect), animated: true)
Expected result is current user place as blue dot placemark to red dot placemark with red line as you can see in the screen shot.
Image:
Related
Currently I can render the spheres using latitude and longitude in ARKit Geolocation Tracking , can anyone please guide me how can I draw polyline between 2 CLLocation in ARKit .
here is a full code to create poly line between two points and also set a width and color of that poly line
var locManager = CLLocationManager()
var currentLocation: CLLocation!
let annotation = MKPointAnnotation()
let annotation2 = MKPointAnnotation()
// MARK:- DRIVER -
var driverLatitute:String!
var driverLongitude:String!
// MARK:- RESTAURANT -
var restaurantLatitude:String!
var restaurantLongitude:String!
IN VIEW DID LOAD
// MARK:- 1 ( MAP ) -
self.locManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
self.locManager.delegate = self
self.locManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locManager.startUpdatingLocation()
print("UPDATE UPDATE")
}
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
print("")
}
DELEGATE METHODS
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//print("**********************")
//print("Long \(manager.location!.coordinate.longitude)")
//print("Lati \(manager.location!.coordinate.latitude)")
//print("Alt \(manager.location!.altitude)")
//print("Speed \(manager.location!.speed)")
//print("Accu \(manager.location!.horizontalAccuracy)")
//print("**********************")
//print(Double((vendorLatitute as NSString).doubleValue))
//print(Double((vendorLongitute as NSString).doubleValue))
/*
// restaurant
self.restaurantLatitude = (dict["deliveryLat"] as! String)
self.restaurantLongitude = (dict["deliveryLong"] as! String)
// driver
self.driverLatitute = (dict["resturentLatitude"] as! String)
self.driverLongitude = (dict["resturentLongitude"] as! String)
*/
let restaurantLatitudeDouble = Double(self.restaurantLatitude)
let restaurantLongitudeDouble = Double(self.restaurantLongitude)
let driverLatitudeDouble = Double("\(manager.location!.coordinate.latitude)") //Double(self.driverLatitute)
let driverLongitudeDouble = Double("\(manager.location!.coordinate.longitude)") // Double(self.driverLongitude)
let coordinate₀ = CLLocation(latitude: restaurantLatitudeDouble!, longitude: restaurantLongitudeDouble!)
let coordinate₁ = CLLocation(latitude: driverLatitudeDouble!, longitude: driverLongitudeDouble!)
/************************************** RESTAURANT LATITUTDE AND LONGITUDE ********************************/
// first location
let sourceLocation = CLLocationCoordinate2D(latitude: restaurantLatitudeDouble!, longitude: restaurantLongitudeDouble!)
/********************************************************************************************************************/
/************************************* DRIVER LATITUTDE AND LINGITUDE ******************************************/
// second location
let destinationLocation = CLLocationCoordinate2D(latitude: driverLatitudeDouble!, longitude: driverLongitudeDouble!)
/********************************************************************************************************************/
//print(sourceLocation)
//print(destinationLocation)
let sourcePin = customPin(pinTitle: "You", pinSubTitle: "", location: sourceLocation)
let destinationPin = customPin(pinTitle: "Driver", pinSubTitle: "", location: destinationLocation)
/***************** REMOVE PREVIUOS ANNOTATION TO GENERATE NEW ANNOTATION *******************************************/
self.mapView.removeAnnotations(self.mapView.annotations)
/********************************************************************************************************************/
self.mapView.addAnnotation(sourcePin)
self.mapView.addAnnotation(destinationPin)
let sourcePlaceMark = MKPlacemark(coordinate: sourceLocation)
let destinationPlaceMark = MKPlacemark(coordinate: destinationLocation)
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { [self] (response, error) in
guard let directionResonse = response else {
if let error = error {
print("we have error getting directions==\(error.localizedDescription)")
}
return
}
/***************** REMOVE PREVIUOS POLYLINE TO GENERATE NEW POLYLINE *******************************/
let overlays = self.mapView.overlays
self.mapView.removeOverlays(overlays)
/************************************************************************************/
/***************** GET DISTANCE BETWEEN TWO CORDINATES *******************************/
let distanceInMeters = coordinate₀.distance(from: coordinate₁)
// print(distanceInMeters as Any)
// remove decimal
let distanceFloat: Double = (distanceInMeters as Any as! Double)
// print(distanceFloat as Any)
// self.lblDistance.text = (String(format: "Distance : %.0f Miles away", distanceFloat/1609.344))
self.lblTotalDistance.text = (String(format: "Distance : %.0f Miles away", distanceFloat/1609.344))
// print(distanceFloat/1609.344)
// print(String(format: "Distance : %.0f Miles away", distanceFloat/1609.344))
let s:String = String(format: "%.0f",distanceFloat/1609.344)
// print(s as Any)
/************************************************************************************/
/***************** GENERATE NEW POLYLINE *******************************/
let route = directionResonse.routes[0]
self.mapView.addOverlay(route.polyline, level: .aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
/************************************************************************************/
}
self.mapView.delegate = self
print("update location after 5 sec")
// self.locManager.stopUpdatingLocation()
// speed = distance / time
}
// line width of poly line
//MARK:- MapKit delegates -
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
My problem is that when I am opening google map using the following code.
It's showing lat long in place of address. But i want to show address in google map, or is there any way to pass custom address along with lat long so that google map will show custom address on search bar (coming on top of the image) and show exact location on map with marker.
I had follow the documentation of URLSchemes given by Google.ios-urlscheme
But didn't get any proper solution which fills my conditions.
UIApplication.shared.openURL(URL(string: "comgooglemaps://?q=40.00026321411133,-83.03424072265625¢er=40.00026321411133,-83.03424072265625"))
You have to pass address venue name also with the lat-long:
import UIKit
import MapKit
func openMapForPlace() {
let lat1 : NSString = self.venueLat
let lng1 : NSString = self.venueLng
let latitude:CLLocationDegrees = lat1.doubleValue
let longitude:CLLocationDegrees = lng1.doubleValue
let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
let address = [CNPostalAddressStreetKey: address ?? "",
CNPostalAddressCityKey: city ?? "",
CNPostalAddressStateKey: state ?? "",
CNPostalAddressPostalCodeKey: zipCode,
CNPostalAddressISOCountryCodeKey: isoCountryCodeKey ?? ""]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: address)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "\(self.venueName)"
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
mapItem.openInMaps(launchOptions: launchOptions)
}
In swift code will be below:
import UIKit
import MapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
openMapForPlace()
}
func openMapForPlace() {
let latitude: CLLocationDegrees = 39.9517958
let longitude: CLLocationDegrees = -75.1611398
let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
let address = [CNPostalAddressStreetKey: "1234 Market St",
CNPostalAddressCityKey: "Philadelphia",
CNPostalAddressStateKey: "Pennsylvania",
CNPostalAddressPostalCodeKey: "19107",
CNPostalAddressISOCountryCodeKey: "USA"]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: address)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "1234 Market St, Philadelphia, Pennsylvania, 19107"
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
mapItem.openInMaps(launchOptions: launchOptions)
}
}
I am currently working on an IOS project in which i have to calculate distance between two location. I have done without using google but i want to use google api to get accurate distance i am sharing my code here
let myLocation = CLLocation(latitude: CLLocationDegrees(latittude[indexPath.row])!, longitude: CLLocationDegrees(longittude[indexPath.row])!)
let lat = UserDefaults.standard.string(forKey: "lat") ?? ""
let long = UserDefaults.standard.string(forKey: "long") ?? ""
let myBuddysLocation = CLLocation(latitude: CLLocationDegrees(lat)!, longitude: CLLocationDegrees(long)!)
Use distance function of CoreLocation Framework,
var startLocation = CLLocation(latitude: startLatitude, longitude: startLongitude)
var endLocation = CLLocation(latitude: endLatitude, longitude: endLongitude)
var distance: CLLocationDistance = startLocation.distance(from: endLocation)
Swift 5+:
As far as I know, there are two ways to find the distance.
If you are looking for driving distance, you can always use MKDirections.
Here is the code for finding driving distance (You can also find walking, and transit distance by changing transport type).
let sourceP = CLLocationCoordinate2DMake( sourceLat, sourceLong)
let destP = CLLocationCoordinate2DMake( desLat, desLong)
let source = MKPlacemark(coordinate: sourceP)
let destination = MKPlacemark(coordinate: destP)
let request = MKDirections.Request()
request.source = MKMapItem(placemark: source)
request.destination = MKMapItem(placemark: destination)
// Specify the transportation type
request.transportType = MKDirectionsTransportType.automobile;
// If you want only the shortest route, set this to a false
request.requestsAlternateRoutes = true
let directions = MKDirections(request: request)
// Now we have the routes, we can calculate the distance using
directions.calculate { (response, error) in
if let response = response, let route = response.routes.first {
print(route.distance) //This will return distance in meters
}
}
If you are only looking for air distance/bird's eye distance/coordinate distance, you can use this code:
let sourceP = CLLocation(latitude: sourceLat, longitude: sourceLong)
let desP = CLLocation(latitude: desLat, longitude: desLong))
let distanceInMeter = sourceP.distance(from: desP)
I'm drawing navigation road at Swift. I'm using current location to another location and made a draw. Afterward, I select another location and redraw it. But even if I write mapView.remove(rotapoly) in my code, it doesnt remove it. How can I solve this?
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
cizim = 1;
let capital = view.annotation as! Station
guard let locValue: CLLocationCoordinate2D = locationManager.location?.coordinate else { return }
let neresi = CLLocationCoordinate2D(latitude: capital.latitude, longitude: capital.longitude)
let nerdeyim = CLLocationCoordinate2D(latitude: locValue.latitude, longitude: locValue.longitude)
let request = MKDirectionsRequest()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: nerdeyim, addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: neresi, addressDictionary: nil))
request.requestsAlternateRoutes = true
request.transportType = .walking
let directions = MKDirections(request: request)
directions.calculate { [unowned self] response, error in
guard let unwrappedResponse = response else { return }
if (unwrappedResponse.routes.count > 0) {
self.showRoute(response!)
}
}
}
func showRoute(_ response: MKDirectionsResponse) {
mapView.remove(rotapoly)
for route in response.routes {
rotapoly = route.polyline
mapView.add(rotapoly, level: MKOverlayLevel.aboveRoads)
for step in route.steps {
print(step.instructions)
}
}
}
use map view method
self.mapview.removeOverlays(self.mapview.overlays)
this will remove all overlays you have added so you have to do whole process again its like reloading map view
Below is the approach to remove travelled polyline from google map iOS Swift:
var oldPolyLines = [GMSPolyline]() /* Global Array Variable of your Class */
Put below code where you are parsing routes and getting new polyline from direction API.
if self.oldPolyLines.count > 0 {
for polyline in self.oldPolyLines {
polyline.map = nil
}
}
self.oldPolyLines.append(yourNewPolyline)
yourNewPolyLine.map = self.mapView
I have one Annotation on my map showing a business location and one button that says get directions, I'm struggling to get the button to open Apple Maps for me with directions to the Annotations location. Here is the code I have done so far:
import UIKit
import MapKit
class FourthViewController: UIViewController , MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let latitude: CLLocationDegrees = 54.647115
let longitude: CLLocationDegrees = -6.659070
let lanDelta: CLLocationDegrees = 0.05
let lonDelta: CLLocationDegrees = 0.05
let span = MKCoordinateSpan(latitudeDelta: lanDelta, longitudeDelta: lonDelta)
let coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegion(center: coordinates, span: span)
map.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.title = "Pose Beauty Salon"
annotation.subtitle = "100 Moneyhaw Road"
annotation.coordinate = coordinates
map.addAnnotation(annotation)
}
#IBAction func mapType(_ sender: AnyObject) {
switch (sender.selectedSegmentIndex) {
case 0:
map.mapType = .standard
case 1:
map.mapType = .satellite
default: // or case 2
map.mapType = .hybrid
}
}
#IBAction func getDirections(_ sender: AnyObject) {
}
}
I've also seen annotations when clicked on that shows more info such as business names, addresses, phone numbers, and URLs is this hard to add also?
This is the code I used to resolve the issue:
let latitude: CLLocationDegrees = 54.647115
let longitude: CLLocationDegrees = -6.659070
let url = URL(string: "https://www.posebeautysalon.com")
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 = "Pose Beauty Salon"
mapItem.phoneNumber = "+442886737777"
mapItem.url = url
mapItem.openInMaps(launchOptions: options)