Search code examples
iosswiftmapkitmkmapview

How to clear map view of directions when user deletes in Swift 3?


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()
    }
}

Solution

  • 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.