Search code examples
iosmkmapviewmkannotationmkpolyline

How to display time on route as google maps


enter image description hereI have created route with multiple annotations. I want to display text between annotations which exactly as attached screen shot.

Can any one help please?

Thanks


Solution

  • I tried something which will show the distance between two annotation but not when you tap on the MKPolylineOverlay. One more important thing I am not maintaining any standards.

    Here is my controller structure.

    import UIKit
    import MapKit
    
    class RouteViewController: UIViewController, MKMapViewDelegate {
    
        @IBOutlet weak var mapView: MKMapView!
    
        //Rest of the code see below
    }
    

    First of all I'll add some annotation to map in the viewDidLoad delegate method as below.

    override func viewDidLoad() {
        super.viewDidLoad()
        self.mapView.delegate = self
    
        let annotation1 = MKPointAnnotation()
        annotation1.title = "Times Square"
        annotation1.coordinate =  CLLocationCoordinate2D(latitude: 40.759011, longitude: -73.984472)
    
        let annotation2 = MKPointAnnotation()
        annotation2.title = "Empire State Building"
        annotation2.coordinate =  CLLocationCoordinate2D(latitude: 40.748441, longitude: -73.985564)
    
        let annotation3 = MKPointAnnotation()
        annotation3.title = "Some Point"
        annotation3.coordinate =  CLLocationCoordinate2D(latitude: 40.7484, longitude: -73.97)
    
        let arrayOfPoints = [ annotation1, annotation2, annotation3]
        self.mapView.addAnnotations(arrayOfPoints)
        self.mapView.centerCoordinate = annotation2.coordinate
    
        for (index, annotation) in arrayOfPoints.enumerate() {
            if index < (arrayOfPoints.count-1) {
                //I am taking the two consecutive annotation and performing the routing operation.
                self.directionHandlerMethod(annotation.coordinate, ePoint: arrayOfPoints[index+1].coordinate)
            }
        }
    }
    

    In the directionHandlerMethod, I am performing the actual request for direction as below,

    func directionHandlerMethod(sPoint: CLLocationCoordinate2D, ePoint: CLLocationCoordinate2D) {
        let sourcePlacemark = MKPlacemark(coordinate: sPoint, addressDictionary: nil)
        let destinationPlacemark = MKPlacemark(coordinate: ePoint, addressDictionary: nil)
        let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
        let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
    
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = sourceMapItem
        directionRequest.destination = destinationMapItem
        directionRequest.transportType = .Automobile
        let directions = MKDirections(request: directionRequest)
        directions.calculateDirectionsWithCompletionHandler {
            (response, error) -> Void in
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
                return
            }
            //I am assuming that it will contain one and only one result so I am taking that one passing to addRoute method
            self.addRoute(response.routes[0])
        }
    }
    

    Next I am adding the polyline route on map in the addRoute method as below,

    func addRoute(route: MKRoute) {
        let polyline = route.polyline
    
        //Here I am taking the centre point on the polyline and placing an annotation by giving the title as 'Route' and the distance in the subtitle
        let annoatation = MKPointAnnotation()
        annoatation.coordinate = MKCoordinateForMapPoint(polyline.points()[polyline.pointCount/2])
        annoatation.title = "Route"
        let timeInMinute = route.expectedTravelTime / 60
        let distanceString =  String.localizedStringWithFormat("%.2f %@", timeInMinute, timeInMinute>1 ? "minutes" : "minute")
        annoatation.subtitle = distanceString
        self.mapView.addAnnotation(annoatation)
    
        self.mapView.addOverlay(polyline)
    }
    

    Next I am implementing the rendererForOverlay delegate method as below,

    func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.strokeColor = UIColor.blueColor()
        renderer.lineWidth = 2
        renderer.lineCap = .Butt
        renderer.lineJoin = .Round
        return renderer
    }
    

    Next one is the important one delegate method which is viewForAnnotation. Here I am doing some things like placing the label instead of the annotation as below,

    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation.title != nil && annotation.title!! == "Route" {
            let label = UILabel()
            label.adjustsFontSizeToFitWidth = true
            label.backgroundColor = UIColor.whiteColor()
            label.minimumScaleFactor = 0.5
            label.frame = CGRect(x: 0, y: 0, width: 100, height: 30)
            label.text = annotation.subtitle ?? ""
            let view = MKAnnotationView()
            view.addSubview(label)
            return view
        }
        return nil
    }