I’m trying to use MKDirection and MKDirectionsRequest to draw a bus route, but I am running into limitations with the API. I have an array of coordiantes of all 72 bus stops along the route, so my first task was to create an array of MKMapItems from those coordinates:

for item in coords {
    let mapItem = MKPlacemark(coordinate: item)
    mapItems.append(MKMapItem(placemark: mapItem))

So far, so good. The next step was to configure the the MKRoute and MKDirectionsRequest:

var busRoute = MKRoute()
let directionsRequest:MKDirectionsRequest = {
    let request = MKDirectionsRequest()
    request.transportType = .automobile
    request.requestsAlternateRoutes = false
    return request

Finally, iterate through the array of MKMapItems and calculate directions from the first stop to the last stop along the route:

for (count, item) in mapItems.enumerated() {
    if count < mapItems.count - 1 {
        directionsRequest.source = item
        directionsRequest.destination = mapItems[count+1]
        let directions = MKDirections(request:directionsRequest)
        directions.calculate(completionHandler: { (response, error) in 
            if error == nil {
                // Add the route to the map
                OperationQueue.main.addOperation {
                    busRoute = response!.routes[0]
                    self.busRouteMapView.add(busRoute.polyline, level: .aboveRoads)
                } else {

This worked as advertised, but only to a point: 50 direction calculations. When I hit 50 API calls, the error returned is Directions Not Available and it restricts any further API calls for about one minute, preventing any opportunity to chain requests together.1 Left as-is, MapKit would return directions for just under 70% of the route, which is obviously not acceptable.

As a test, I tried to use the first and last set of coordinates and then every second set of coordinates in between. Zoomed out, it looked promising. Zoomed in, not so much — it lead to cut corners.

I don’t want to use MKPolyline to draw a waypoint-to-waypoint look that would ignore the roads. For the moment, I am stuck.

  1. Unhelpfully, I’ve found no mention of this API limitation in the documentation.