iosswiftmkmapviewmkoverlay

I cannot get my MKRoute to show up on a MapView


I am trying to add an MKOverlay (my MKRoute) to my MapView, but I cannot figure out what I am doing wrong. This is pretty sloppy because I'm experimenting with it before I implement it in my app.

Here's the code:

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    @IBOutlet var map: MKMapView!

    var geocoder:CLGeocoder = CLGeocoder()
    var location:CLLocation = CLLocation(latitude: 38, longitude: -77)
    var next:CLLocation = CLLocation(latitude: 38.9, longitude: -77.61)
    var locMark:MKPlacemark?
    var destMark:MKPlacemark?
    var manager:CLLocationManager = CLLocationManager()
    var source:MKMapItem?
    var destination:MKMapItem?
    var request:MKDirectionsRequest = MKDirectionsRequest()
    var directions:MKDirections = MKDirections()
    var directionsResponse:MKDirectionsResponse = MKDirectionsResponse()
    var route:MKRoute! = MKRoute()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.map.delegate = self
        manager.requestAlwaysAuthorization()

        let latDelt = 0.05
        let lonDelt = 0.05

        let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: latDelt, longitudeDelta: lonDelt)
        let region:MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), span: span)
        map.setRegion(region, animated: true)


        map.mapType = MKMapType.Satellite


        locMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), addressDictionary: nil)
        destMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(next.coordinate.latitude, next.coordinate.longitude), addressDictionary: nil)

        source = MKMapItem(placemark: locMark)
        destination = MKMapItem(placemark: destMark)

        request.setSource(source)
        request.setDestination(destination)
        request.transportType = MKDirectionsTransportType.Automobile
        request.requestsAlternateRoutes = true

        let directions = MKDirections(request: request)

        directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse?, error:NSError?) -> Void in

            if error == nil {
                self.directionsResponse = response!
                self.route = self.directionsResponse.routes[0] as! MKRoute
                self.map.addOverlay(self.route.polyline)
            } else {
                println(error)
            }
        }

        func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {

            if overlay is MKPolyline {
                var pr = MKPolylineRenderer(overlay: overlay)
                pr.strokeColor = UIColor.purpleColor()
                pr.lineWidth = 5
                return pr
            }
            return nil
        }
    }

I don't get any errors printed, but not route shows up on the map at all.


Solution

  • The problem is that the rendererForOverlay function is nested inside viewDidLoad:

    override func viewDidLoad() {
        //your viewDidLoad code is here...
    
        //rendererForOverlay is declared here inside viewDidLoad...
        func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
            ...
        }
    
    }  // <-- closing brace of viewDidLoad
    

    Because of this, the rendererForOverlay function is hidden from the map view and it does not call it resulting in no overlay displaying.

    To fix this, move the rendererForOverlay function outside viewDidLoad so that it's visible to the rest of the class:

    override func viewDidLoad() {
        //your viewDidLoad code is here...
    
    }  // <-- closing brace of viewDidLoad
    
    //put rendererForOverlay here outside viewDidLoad...
    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        ...
    }