I need some help to solve this problem. So, I have a turn-by-turn navigation where when user search for places and it will give turn-by-turn navigation. But, when user deletes the places name, but it still shows on the map view. Is there a way I can delete the map view when user deletes the places or address name? Thanks for the help.
here is my code:
import UIKit
import MapKit
import CoreLocation
import AVFoundation
class NavigateVC: UIViewController {
@IBOutlet weak var directionLabel: UILabel!
@IBOutlet weak var search: UISearchBar!
@IBOutlet weak var mapa: MKMapView!
let locationManager = CLLocationManager()
var currentCoordinate: CLLocationCoordinate2D!
var steps = [MKRouteStep]()
let speechSynthesizer = AVSpeechSynthesizer()
var stepCounter = 0
override func viewDidLoad() {
super.viewDidLoad()
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.startUpdatingLocation()
// Show an alert view to the user - as a new feature to the app.
let alert = UIAlertController(title: "Welcome", message: "You can now navigate to your favorite place with turn-by-turn navigation. Simply, enter a place name or full address to navigate to your destination. Note: Multiple destination navigation will show on the map view. Choose your destination wisely. ", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
switch action.style{
case .default:
print("default")
case .cancel:
print("cancel")
case .destructive:
print("destructive")
}}))
self.present(alert, animated: true, completion: nil)
}
func getDirections(to destination: MKMapItem) {
let sourcePlacemark = MKPlacemark(coordinate: currentCoordinate)
let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
let directionsRequest = MKDirectionsRequest()
directionsRequest.source = sourceMapItem
directionsRequest.destination = destination
directionsRequest.transportType = .automobile
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response, _) in
guard let response = response else { return }
guard let primaryRoute = response.routes.first else { return }
self.mapa.add(primaryRoute.polyline)
self.locationManager.monitoredRegions.forEach({ self.locationManager.stopMonitoring(for: $0) })
self.steps = primaryRoute.steps
for i in 0 ..< primaryRoute.steps.count {
let step = primaryRoute.steps[i]
print(step.instructions)
print(step.distance)
let region = CLCircularRegion(center: step.polyline.coordinate,
radius: 20,
identifier: "\(i)")
self.locationManager.startMonitoring(for: region)
let circle = MKCircle(center: region.center, radius: region.radius)
self.mapa.add(circle)
}
let initialMessage = "In \(self.steps[0].distance) meters, \(self.steps[0].instructions) then in \(self.steps[1].distance) meters, \(self.steps[1].instructions)."
self.directionLabel.text = initialMessage
let speechUtterance = AVSpeechUtterance(string: initialMessage)
self.speechSynthesizer.speak(speechUtterance)
self.stepCounter += 1
}
}
}
extension NavigateVC: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
guard let currentLocation = locations.first else { return }
currentCoordinate = currentLocation.coordinate
mapa.userTrackingMode = .followWithHeading
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("ENTERED")
stepCounter += 1
if stepCounter < steps.count {
let currentStep = steps[stepCounter]
let message = "In \(currentStep.distance) meters, \(currentStep.instructions)"
directionLabel.text = message
let speechUtterance = AVSpeechUtterance(string: message)
speechSynthesizer.speak(speechUtterance)
} else {
let message = "Arrived at destination"
directionLabel.text = message
let speechUtterance = AVSpeechUtterance(string: message)
speechSynthesizer.speak(speechUtterance)
stepCounter = 0
locationManager.monitoredRegions.forEach({ self.locationManager.stopMonitoring(for: $0) })
}
}
}
extension NavigateVC: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
let localSearchRequest = MKLocalSearchRequest()
localSearchRequest.naturalLanguageQuery = searchBar.text
let region = MKCoordinateRegion(center: currentCoordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
localSearchRequest.region = region
let localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.start { (response, _) in
guard let response = response else { return }
guard let firstMapItem = response.mapItems.first else { return }
self.getDirections(to: firstMapItem)
}
}
}
extension NavigateVC: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .blue
renderer.lineWidth = 10
return renderer
}
if overlay is MKCircle {
let renderer = MKCircleRenderer(overlay: overlay)
renderer.strokeColor = .red
renderer.fillColor = .red
renderer.alpha = 0.5
return renderer
}
return MKOverlayRenderer()
}
}
Use this function
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
}
So that every time there is a change in serachbar text, this function will be called. You can reload the map whwnever required. I think this is what you are looking for.