HERE iOS SDK Developer's Guide

Urban Mobility Routing

Similar to car and pedestrian routing through NMACoreRouter, you can perform public transport routing through NMAUrbanMobilityRouter, while specifying options through the NMARoutingMode class.

With the Urban Mobility Routing feature, you can calculate transit routes and fare costs by using real time online timetable information.

Notes and Disclaimers

Before using the Transit Routing feature, please be aware of the following:

  • Transit routing is currently offered as a beta feature. APIs may change without notice.
  • Access to the Transit Routing feature is restricted. Contact a HERE representative ( for more information and to request for access.
  • As of HERE SDK v3.2, NMARouteManager and NMATransportModePublicTransport have been deprecated. Transit routing is now handled by a set of Urban Mobility (UM) routing classes, with the main entry point being the NMAUrbanMobilityRouter class.

Urban Mobility Routing Example

The following is an example of how to calculate a public transit route that connects two waypoints (start and destination):

  1. Declare a NMAUrbanMobilityRouter instance.
    // Declare the variable (the NMAUrbanMobilityRouter)
    _router = [[NMAUrbanMobilityRouter alloc] init];
  2. Create an array containing two NMAGeoCoordinates waypoints.
    // Create the RoutePlan and add two waypoints
    NSMutableArray* stops = [[NSMutableArray alloc] initWithCapacity:4];
    NMAGeoCoordinates *coordsStart = [NMAGeoCoordinates geoCoordinatesWithLatitude:49.261789 longitude:-122.999591];
    NMAGeoCoordinates *coordsEnd = [NMAGeoCoordinates geoCoordinatesWithLatitude:49.254150 longitude:-123.016819];
    NMAWaypoint *waypointStart = [NMAWaypoint new];
    waypointStart.originalPosition = coordsStart;
    waypointStart.navigablePosition = coordsStart;
    NMAWaypoint *waypointEnd = [NMAWaypoint new];
    waypointEnd.originalPosition = coordsEnd;
    waypointEnd.navigablePosition = coordsEnd;
    [stops addObject:waypointStart];
    [stops addObject:waypointEnd];
    Note: Destinations that are too close to the starting waypoint are not supported. Use a pedestrian route calculation instead.
  3. Create a new NMARoutingMode object and set the desired options.
    // Create the NMARoutingMode and set its transport mode and routing type
    _currentRoutingMode =[[NMARoutingMode alloc] init];
    _currentRoutingMode.transportMode = NMATransportModeUrbanMobility;
  4. Create a NMAUrbanMobilityCalculateResultBlock by handling the NMAUrbanMobilityRouteResult and NMAUrbanMobilityError. Note that the returned object, NMAUrbanMobilityRouteResult, may contain multiple NMAUrbanMobilityRoute instances.

    NMAUrbanMobilityRoute can be used to create a NMAMapRoute instance for rendering purposes.

    Note: To perform subsequent route calculations, check if the returned NMAUrbanMobilityRouteResult object supports subsequent routes by checking the subsequentRouteSupported property, and call calculateSubsequentRouteWithRouteResult:withSubsequentRouteType:withRouteCount:completionBlock: as needed. For more information on subsequent routes, see the Subsequent Routes section in this chapter.
  5. After adding the completion block class, calculate the route by calling calculateRouteWithStops:routingMode:completionBlock:.
    __block NSProgress *progress;
    progress = [(NMAUrbanMobilityRouter *) _router calculateRouteWithStops:_waypoints
         completionBlock:^(NMAUrbanMobilityRouteResult *routeResult, NMARoutingError error) {
         // completion block logic
         // access to NMAUrbanMobilityRouteResult or error
  6. You are required to display the source attribution, retrieved through the sourceAttribution property in NMAUrbanMobilityRoute, somewhere near the route results.
  7. Geometry, line color, and other types of display information can be retrieved through NMATransitManeuver objects. You can retrieve and display ticket fare information by using the NMAUrbanMobilityTariff objects inside NMAUrbanMobilityRoute.

Handling Routes

Similar to a transit route returned from NMACoreRouter, when a transit route is found, NMAUrbanMobilityRouter returns the calculation result block and route result via calculateRouteWithStops:routingMode:completionBlock:. An NMAUrbanMobilityRoute contains one or more maneuvers, represented by the NMAManeuver class. Each of these maneuvers is either a pedestrian or a public transit maneuver. If a maneuver is a public transit maneuver, information specific for transit can be accessed by downcasting the NMAManeuver to NMATransitManeuver. An NMATransitManeuver contains one or more NMATransitRouteElement objects. Each NMATransitRouteElement object contains the departure station, the arrival station and travel time of that transit maneuver.
Note: Transit directions are only available in certain areas of the world.
Transit directions do not include directions from the arrival stop platform to its access point, which may be some distance away, especially for metro/trains. To further assist end users, you can revise the above example as follows:

// If the route was calculated successfully
if(!error && routes && routes.count > 0)
  NMARoute* route = [routes objectAtIndex:0];
  NSArray* maneuvers = route.maneuvers;

  for (NSUInteger index=0; index < maneuvers.count; index++) {
  NMAManeuver* maneuver = [maneuvers objectAtIndex:index];
  NMAManeuver* nextManeuver = nil;
  if (index+1<maneuvers.count) {
    nextManeuver = [maneuvers objectAtIndex:index+1];
  if (maneuver.transportMode==NMATransportModePublicTransport) {
    NMATransitManeuver* transitManeuver = (NMATransitManeuver*)maneuver;
    NSArray* transitRouteElements = transitManeuver.transitRouteElements;

    // Add info to help end-users locate access point of the metro/train platform
    if ((transitManeuver.transitType==NMATransitTypeMonorail ||
      transitManeuver.transitType==NMATransitTypeLightRail ||
      transitManeuver.transitType==NMATransitTypeMetroRail ||
      transitManeuver.transitType==NMATransitTypeRegionalRail ||
      transitManeuver.transitType==NMATransitTypeHighSpeedTrain ||
      transitManeuver.transitType==NMATransitTypeIntercityTrain ||
      transitManeuver.transitType==NMATransitTypeRegionalTrain) &&
      nextManeuver &&
      nextManeuver.nextRoadName &&
      // If this maneuver is transit and the next maneuver is walking
      NSLog(@"Take %@ at %@ towards %@ and get off at %@ after %d stops then head towards %@ exit",
        transitManeuver.lineName, transitManeuver.departureStopName,
        transitManeuver.terminusStopName, transitManeuver.arrivalStopName,
        transitRouteElements.count, nextManeuver.nextRoadName);
    } else {
      // Otherwise, present the transit info normally
      NSLog(@"Take %@ at %@ towards %@ and get off at %@ after %d stops",
        transitManeuver.lineName, transitManeuver.departureStopName,
        transitManeuver.terminusStopName, transitManeuver.arrivalStopName,
  } else {
    if (maneuver.action!=NMAManeuverActionEnd) {
      NSLog(@"Walk %d meters", maneuver.distanceToNextManeuver);
    } else {
      NSLog(@"You've arrived at your destination");
else if(error)
  // Display a message indicating route calculation failed

As with other transit routes, when displaying transit routes, set the map scheme to include transit and use setBoundingBox:withAnimation: to display the entire route.

// sets the map scheme to include transit.
[mapView setMapScheme:NMAMapSchemeNormalDayTransit];
// zoom to display the entire route
[mapView setBoundingBox:route.boundingBox withAnimation:NMAMapAnimationBow];
Figure 1. Transit Route

Subsequent Routes

The NMAUrbanMobilityRouter class supports subsequent route calculations based on an initial set of route results. For example, you can use NMAUrbanMobilityRouter to launch a route calculation, and then use the returned NMAUrbanMobilityRouteResult to launch a subsequent route calculation for three routes that have the same waypoints, but have an earlier departing time.

You do not need to specify a timestamp for the subsequent calculation. The HERE SDK will automatically return your desired number of results based on whether you specified earlier or later. In other words, you can "slide" the window of interested route results by specifying NMASubsequentRouteTypeForward or (NMASubsequentRouteTypeBackward) and the desired number of results.

The method to perform this calculation is calculateSubsequentRouteWithRouteResult:withSubsequentRouteType:withRouteCount:completionBlock:.

Online Timetables and Fallback Scenarios

Wherever possible, the HERE SDK performs route calculations using the latest online timetable data from municipalities. This is performed automatically when you launch a transit routing request, but the following conditions must be fulfilled:

  • Your application must have an active data connection. If there is no data connection, an estimated routing is performed instead.
  • The route must be between two endpoints—an origin and a destination. Multiple endpoints are not supported.

This type of calculation only returns a maximum of ten route results, even if the NMARoutingMode resultLimit property is set to a higher number.

Note: The maximumChanges property is only applicable for the first route result in this route calculation mode. Also, the acceptable values for maximumChanges are limited to ten or under.
Note: Contractual limitations exist for Online Timetable coverage in Paris, France and Germany. Contact your HERE Sales, Marketing, or Product representative for additional details.