Turn by turn navigation to annotation with Apple Maps - ios

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)

Related

How can I draw a polyline in ARKit using latitude and longitude?

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
}

How to get directions from user location to another specific location?

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:

google map url - how do I show address when passing lat and long in url to google maps in iOS?

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&center=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)
}
}

How can I read values in my Firebase database using swift and then make annotations on a map?

I am a starter at swift and Xcode and just need some help with my code. I have made a firebase database:
And I have changed the rules:
I have a map view and have coded each annotation on the map and just need someone to show me how to read all of the locations in the database and then put them as annotations on the map view. This is all of my code so far:
import UIKit
import MapKit
import FirebaseDatabase
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
map.showsUserLocation = true
// Do any additional setup after loading the view.
map.mapType = .satellite
self.map.isZoomEnabled = false
map.showsCompass = false
map.isRotateEnabled = false
let latitude: CLLocationDegrees = 51.743370
let longitude: CLLocationDegrees = -2.279179
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 = "School House"
annotation.subtitle = "Main School Building"
annotation.coordinate = coordinates
map.addAnnotation(annotation)
map.selectAnnotation(annotation, animated: true)
let annotationCollingwood = MKPointAnnotation()
annotationCollingwood.title = "Collingwood"
annotationCollingwood.subtitle = "Day House"
annotationCollingwood.coordinate = CLLocationCoordinate2D(latitude: 51.742688, longitude: -2.279362)
map.addAnnotation(annotationCollingwood)
let annotationSibly = MKPointAnnotation()
annotationSibly.title = "Sibly"
annotationSibly.subtitle = "Musical Theatre"
annotationSibly.coordinate = CLLocationCoordinate2D(latitude: 51.743518, longitude: -2.279796)
map.addAnnotation(annotationSibly)
map.camera.altitude = 300.00
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func menuButton(_ sender: Any) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "MenuViewController") as! MenuViewController
self.present(resultViewController, animated:true, completion:nil)
}
}
In firebase get list of location using below code:
#property (strong, nonatomic) FIRDatabaseReference *ref;
self.ref = [[FIRDatabase database] reference];
[_ref child:#"Locations"]
[_ref observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot *snapshot) {
// Loop over children
NSEnumerator *children = [snapshot children];
FIRDataSnapshot *child;
while (child = [children nextObject]) {
// here you can set your annotations
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]
annotation.title = child.key
annotation.subtitle = #""
annotation.coordinate = CLLocationCoordinate2D (latitude: child.value[#"Latitude"], longitude: child.value[#"Latitude"])
[map addAnnotation:annotation]
}
}];
I am unaware of FIRDataSnapshot class so to take place name from key of child. But sure for locations key. Hope this helps
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.removeItemAtPath("**Folder Name of your project**")
}
catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
}
Try entering this code. It should allow you to send and recive data.

How can I add a GPS that leads to pins on map?

I am making an app that displays pins ( that the user adds) on a map and saves them in a tableview and I would like to have a GPS lead the user when they tap on a button that opens the GPS so they can get to that place, how could I do this, this is the code I have in the table view:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = places[indexPath.row]["name"]
return cell
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
activePlace = indexPath.row
return indexPath
}
and this is the code I have in the map view:
func action(gestureRecognizer:UIGestureRecognizer) {
if gestureRecognizer.state == UIGestureRecognizerState.Began {
var touchPoint = gestureRecognizer.locationInView(self.Map)
var newCoordinate = self.Map.convertPoint(touchPoint, toCoordinateFromView: self.Map)
var location = CLLocation(latitude: newCoordinate.latitude , longitude: newCoordinate.longitude)
CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
var title = ""
if (error == nil) {
if let p = CLPlacemark(placemark: placemarks?[0] as! CLPlacemark) {
var subThoroughfare: String = ""
var thoroughfare: String = ""
if p.subThoroughfare != nil {
subThoroughfare = p.subThoroughfare
}
if p.thoroughfare != nil {
thoroughfare = p.thoroughfare
}
title = "\(subThoroughfare) \(thoroughfare)"
}
}
if title == "" {
title = "added \(NSDate())"
}
places.append(["name":title,"lat":"\(newCoordinate.latitude)","lon":"\(newCoordinate.longitude)"])
I have been trying the code below to add the GPS but I have a predefined destination so I suppose I have to change the coordinates to something else but I dont know exactly what, thanks for the help !
UIApplication.sharedApplication().openURL(NSURL(string: "http://maps.apple.com/maps?daddr=34.539250,-117.222025")!)
I am also using this piece of code for the user location
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var userLocation:CLLocation = locations[0] as! CLLocation
var latitude = userLocation.coordinate.latitude
var longitude = userLocation.coordinate.longitude
var coordinate = CLLocationCoordinate2DMake(latitude, longitude)
var latDelta:CLLocationDegrees = 0.01
var lonDelta:CLLocationDegrees = 0.01
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
var region:MKCoordinateRegion = MKCoordinateRegionMake(coordinate, span)
self.Map.setRegion(region, animated: true)
To piggyback off of #Mingebag 's answer, in response to your comment there:
You need to set the variables in the openMapForPlace() method he provided to the ones that correspond to the gps position you want to get directions to in the apple maps app.
Wherever you call this method, you can pass it the variables you need. For this to work, you really just need to give it Lat / Lon somehow.
You could do that by making it be:
func openMapsForPlace(lat: Double, lon: Double) {}
or whatever format you have those in.
You can also just put this code wherever you want if you have a better place for it to execute from:
let regionDistance:CLLocationDistance = 10000
//set the coordinates with your variables
var coordinates = CLLocationCoordinate2DMake(newCoordinates.latitude, newCoordinates.longitude)
let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)
var options = [
MKLaunchOptionsMapCenterKey: NSValue(MKCoordinate: regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(MKCoordinateSpan: regionSpan.span)
]
//now your placemark will have the lat long you put in above
var placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
var mapItem = MKMapItem(placemark: placemark)
mapItem.name = "\(self.venueName)"
//this line then launches the app for you
mapItem.openInMapsWithLaunchOptions(options)
Let us assume you have location enabled so you just need the "user location" that you have saved in your table then try this:
Just pass your lang,lat and that should do it ^^
func openMapForPlace() {
var lat1 : NSString = self.venueLat
var lng1 : NSString = self.venueLng
var latitute:CLLocationDegrees = lat1.doubleValue
var longitute:CLLocationDegrees = lng1.doubleValue
let regionDistance:CLLocationDistance = 10000
var coordinates = CLLocationCoordinate2DMake(latitute, longitute)
let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)
var options = [
MKLaunchOptionsMapCenterKey: NSValue(MKCoordinate: regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(MKCoordinateSpan: regionSpan.span)
]
var placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
var mapItem = MKMapItem(placemark: placemark)
mapItem.name = "\(self.venueName)"
mapItem.openInMapsWithLaunchOptions(options)
}
If there are any question feel free to ask

Resources