Reputation: 1184
I need current location as a source and searched location as a destination, but I got the current location but here I am unable to bring coordinates(latitude and longitude) from searched location to destination. here my destination shows nil why? Below is the code please help me.
import UIKit
import MapKit
import CoreLocation
class MapSampViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UISearchBarDelegate {
//Privacy - Location When In Use Usage Description, Privacy - Location Always Usage Description-------these two add in info.plist
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var mapView: MKMapView!
var source: CLLocationCoordinate2D!
var destination: CLLocationCoordinate2D!
var myaddress:String!
var mycity:String!
var mystate:String!
var mycountry:String!
var mytitle:String!
var mylongitude:String!
var mylatitude:String!
var locationtoSearch:String!
let locationManager = CLLocationManager()
var currentlocationPlacemark: CLPlacemark!
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
mapView.delegate = self
mapView.showsScale = true
mapView.showsPointsOfInterest = true
mapView.showsUserLocation = true
if CLLocationManager.locationServicesEnabled()
{
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
// self.showDirection()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
locationtoSearch = self.searchBar.text
var geocoder:CLGeocoder = CLGeocoder()
geocoder.geocodeAddressString(locationtoSearch!, completionHandler: {(placemarks, error) -> Void in
if((error) != nil)
{
print("Error", error)
}
else if let placemark = placemarks?[0] as? CLPlacemark {
var coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
var pointAnnotation:MKPointAnnotation = MKPointAnnotation()
pointAnnotation.coordinate = coordinates
print(coordinates)
// pointAnnotation.title = "\(String(describing: placemark.name)),\(String(describing: placemark.locality)), \(String(describing: placemark.administrativeArea)), \(String(describing: placemark.country))"
self.myaddress = placemark.name
self.mycity = placemark.locality
self.mystate = placemark.administrativeArea
self.mycountry = placemark.country
pointAnnotation.title = "\(self.myaddress),\(self.mycity),\(self.mystate),\(self.mycountry)"
self.mylongitude = String(stringInterpolationSegment: placemark.location?.coordinate.longitude)
self.mylatitude = String(stringInterpolationSegment: placemark.location?.coordinate.latitude)
self.mapView?.addAnnotation(pointAnnotation)
self.mapView?.centerCoordinate = coordinates
print("coordinates \(coordinates)")
print("The latitude \(self.mylatitude)")
print("The longitude \(self.mylongitude)")
self.mapView?.selectAnnotation(pointAnnotation, animated: true)
}
})
self.showDirection()//i called here or in view viewDidLoad
let annotationsToRemove = mapView.annotations.filter { $0 !== self.mapView.userLocation
}
mapView.removeAnnotations( annotationsToRemove )
}
func showDirection()
{
source = locationManager.location?.coordinate//17.6881° N, 83.2131° E
// let destination = CLLocationCoordinate2DMake(24.9511, 121.2358 )//If i give like this its working
destination = CLLocationCoordinate2DMake(Double(mylongitude)!, Double(mylongitude)!)//fatal error: unexpectedly found nil while unwrapping an Optional value
let sourcePlacemark = MKPlacemark(coordinate: source!)
let destinationPlacemark = MKPlacemark(coordinate: destination)
let sourceItem = MKMapItem(placemark: sourcePlacemark)
let destinationItem = MKMapItem(placemark: destinationPlacemark)
let directionReq = MKDirectionsRequest()
directionReq.source = sourceItem
directionReq.destination = destinationItem
directionReq.transportType = .automobile
let directions = MKDirections(request: directionReq)
directions.calculate(completionHandler: {(response, error) in
if error != nil {
print("Error getting directions")
}
else {
let route = response?.routes[0]
self.mapView.add((route?.polyline)!, level:.aboveRoads)
let rekt = route?.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rekt!), animated: true)
}
})
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let rendrer = MKPolylineRenderer(overlay: overlay)
rendrer.strokeColor = UIColor.blue
rendrer.lineWidth = 3
return rendrer
}
}
here i called showDirection()
func in searchBarSearchButtonClicked
but it is getting called before coming here why?
Upvotes: 1
Views: 72
Reputation: 783
Direction requests are executed asynchronously. This means that the rest of your app doesn't wait for the direction to be fetched.
Your showDirection function is both fetching the direction and adding it to the mapView. It would be best to separate these functionalities. You can fetch the direction, update a route variable and have an observer on it which will add the route to the map once it has been fetched.
@IBOutlet weak var mapView: MKMapView!
var route: MKRoute? {
didSet {
mapView.add((route?.polyline)!, level:.aboveRoads) }
}
Upvotes: 0