Search code examples
swiftxcodemapkitdrawpolyline

Draw polyline with mapkit Swift 3


I want to draw a polyline from the current user location to an annotation point but it doesn't appear to draw anything:

@IBAction func myButtonGo(_ sender: Any) {
    showRouteOnMap()
}

func showRouteOnMap() {
    let request = MKDirectionsRequest()

    request.source = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D.init(), addressDictionary: nil))
    request.destination = MKMapItem(placemark: MKPlacemark(coordinate: (annotationCoordinatePin?.coordinate)!, addressDictionary: nil))
    request.requestsAlternateRoutes = true
    request.transportType = .automobile

    let directions = MKDirections(request: request)

    directions.calculate { [unowned self] response, error in guard let unwrappedResponse = response else { return }

        if (unwrappedResponse.routes.count > 0) {
            self.mapView.add(unwrappedResponse.routes[0].polyline)
            self.mapView.setVisibleMapRect(unwrappedResponse.routes[0].polyline.boundingMapRect, animated: true)
        }
    }
}

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
    renderer.strokeColor = UIColor.black
    return renderer
}

I tried to run in debug mode and it stops on the break point at line of:

directions.calculate { [unowned self] response, error in guard let unwrappedResponse = response else { return }

What is the cause of this error?


Solution

  • If it's stopping there, make sure you don't have a breakpoint there:

    enter image description here

    The dark blue indicator in the left margin indicates that there is a breakpoint there. If you have a breakpoint, just click on it to disable it (change it to light blue) or drag it off to remove it.

    If that's not the problem (i.e. it's really crashing), then we need to know what sort of crash it is, what showed up in the console, etc.

    If it's not crashing, but simply not drawing the route, make sure you've specified the delegate of the map view (either in viewDidLoad or right in IB).


    That having been said, a couple of other observations, though:

    1. Your starting coordinate is CLLocationCoordinate2D() (i.e. lat and long of 0, 0, i.e. in the Pacific Ocean). This wouldn't cause it to crash, but if you examine the error object, its localized description will say:

      Directions Not Available

      You should correct the coordinate for the source.

    2. You should be wary of unowned self with asynchronous methods, because it's always possible that self could be released by the time the directions are returned, and it would crash. Using [weak self] is safer.

    Thus:

    let request = MKDirectionsRequest()
    request.source = MKMapItem(placemark: MKPlacemark(coordinate: sourceCoordinate))
    request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destinationCoordinate))
    request.requestsAlternateRoutes = true
    request.transportType = .automobile
    
    let directions = MKDirections(request: request)
    directions.calculate { [weak self] response, error in
        guard let response = response, error == nil, let route = response.routes.first else {
            print(error?.localizedDescription ?? "Unknown error")
            return
        }
    
        self?.mapView.add(route.polyline)
    }