MapDirections PRO

MapDirections plans routes between two endpoints using MapKit. Two entry points:

  • MapDirections.calculate(options) — full route(s) with turn-by-turn steps and a ready-to-render polyline.
  • MapDirections.calculateETA(options) — travel time / distance / arrival window only. Cheaper and faster than calculate when you don't need the geometry.

Both APIs are network-backed by Apple's directions servers and require no iOS system permissions. The result is plain data — no opaque handles to dispose.

Pair with the views layer: route.coordinates is shaped exactly for <MapPolyline coordinates={route.coordinates}> from the <Map> view.


calculate — plan a route

const resp = await MapDirections.calculate({
  source: { latitude: 31.2304, longitude: 121.4737 },        // People's Square
  destination: { latitude: 31.2397, longitude: 121.4994 },   // Lujiazui
  transportType: "walking",
})

const route = resp.routes[0]
console.log(route.distance, "m")             // total distance in meters
console.log(route.expectedTravelTime, "s")   // ETA in seconds
console.log(route.steps.length, "steps")     // turn-by-turn count

Options

OptionTypeDescription
sourceDirectionsEndpointRequired. Bare MapCoordinate or { coordinate, name? }.
destinationDirectionsEndpointRequired. Same shape as source.
transportType"automobile" | "walking" | "transit" | "any"Default "automobile".
requestsAlternateRoutesbooleanDefault false. Up to 3 routes when supported (driving / highway only).
departureDateDatePlan a route departing at this time. Wins over arrivalDate if both are set.
arrivalDateDatePlan a route arriving by this time.
tollPreference"any" | "avoid"Default "any".
highwayPreference"any" | "avoid"Default "any".

DirectionsResponse

FieldTypeDescription
sourceMapItemSame shape as MapSearch.locate results — includes coordinate, placemark, formattedAddress, etc.
destinationMapItemSame shape.
routesDirectionsRoute[]At least 1 entry.

DirectionsRoute

FieldTypeDescription
namestringRoute label (e.g. road name).
distancenumberTotal distance in meters.
expectedTravelTimenumberETA in seconds.
transportTypeTransportTypeMode used for this route.
coordinatesMapCoordinate[]Ready-to-render polyline. Pass straight to <MapPolyline coordinates={...}>.
stepsDirectionsRouteStep[]Turn-by-turn instructions.
hasTollsbooleanAny tolled segments.
hasHighwaysbooleanAny highway segments.
advisoryNoticesstring[]Optional advisory text from Apple.

Rendering with <MapPolyline>

<Map cameraPosition={position}>
  <Marker title="Start" coordinate={route.coordinates[0]} tint="systemGreen" />
  <Marker title="End"   coordinate={route.coordinates.at(-1)!} tint="systemRed" />
  <MapPolyline
    coordinates={route.coordinates}
    strokeColor="systemBlue"
    strokeStyle={{ lineWidth: 4, lineCap: "round" }}
  />
</Map>

calculateETA — time / distance only

const eta = await MapDirections.calculateETA({
  source: { latitude: 31.2304, longitude: 121.4737 },
  destination: { latitude: 31.2397, longitude: 121.4994 },
  transportType: "automobile",
})

console.log(eta.expectedTravelTime, "s")
console.log(eta.distance, "m")
console.log(eta.expectedArrivalDate.toLocaleString())

Use this when you only need the headline numbers — it skips downloading the full route geometry, so it's noticeably faster than calculate.


Notes & limitations

  • Transit (transportType: "transit") is supported in a limited set of regions. Outside those, the request rejects with directionsNotFound. For broad coverage prefer "automobile" or "walking".
  • Alternates typically only return multiple routes for driving on roads with realistic alternatives — walking usually returns a single route.
  • No cancel handle: a new calculate call doesn't cancel an in-flight one. Responses arrive in whatever order Apple's servers return them, so if you fire requests rapidly (e.g. while the user is moving sliders) implement your own "latest-wins" guard.
  • departureDate and arrivalDate are mutually exclusive: if both are provided, departureDate wins; arrivalDate is ignored.