Steve Gear Steve Gear - 6 months ago 18
iOS Question

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?



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() {
    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.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)")
        //I am assuming that it will contain one and only one result so I am taking that one passing to addRoute method

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


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()
        return view
    return nil