A turn-by-turn data feed provides navigation-only information to devices not
designed for map-based navigation guidance. It provides upcoming maneuvers with
elements you supply:

- icons (left, right, U-turn)
- turn numbers in roundabouts
- road names
- estimated distances and time to the next navigation step or final destination

You can use the turn-by-turn feed to create experiences where the full
Navigation SDK UI is not appropriate, such as for small screen displays. For
example, you might use this for two-wheeled vehicle riders, where you can
project navigation-only guidance to help them reach their destinations faster
and more confidently with minimal distractions.

## Essential navigation display elements

![A mobile screen that displays an upcoming right turn in 50 feet onto Church
Street. At the bottom of the screen, time remaining to destination is 13
minutes, and distance remaining is 2.1
miles.](https://developers.google.com/static/maps/documentation/navigation/ios-sdk/images/essential_nav_display_elements.png)

The primary fields for each navigation step are the full road name,
maneuver, and total distance of the step, which are available in
[`GMSNavigationStepInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationStepInfo.md.txt).

For the overall trip, you may want to display the remaining time and distance
to the current step or to the destination, all of which are available in
[`GMSNavigationNavInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationNavInfo.md.txt).
The image to the right shows an example of these essential navigation elements.

## Set up an event listener

To use navigation-only data, you have to implement an event listener for the
`didChangeNavInfo` event. Within the event listener, access trip and
step information to provide turn by turn navigation to your users.

To implement event handlers, the view controller of the map must implement the
[`GMSNavigatorListener`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Protocols/GMSNavigatorListener.md.txt)
protocol. For detailed information on handling events in the
Navigation SDK for iOS, see [Listen for navigation events](https://developers.google.com/maps/documentation/navigation/ios-sdk/events.md.txt).

## Handling the `didChangeNavInfo` event

Create a listener for the `didChangeNavInfo` event to add turn-by-turn support
to your app. In the event listener, use the following classes and enums to
control turn-by-turn navigation:

- [`GMSNavigationNavInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationNavInfo.md.txt)
  --- Class defining information about the state of navigation.

- [`GMSNavigationStepInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationStepInfo.md.txt)
  --- Class defining information about a single step along a navigation
  route.

- [`GMSNavigationNavState`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Enums/GMSNavigationNavState.md.txt)
  --- Enum defining the current state of a navigation, such as enroute,
  rerouting, or stopped.

- [`GMSNavigationDrivingSide`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Enums/GMSNavigationDrivingSide.md.txt)
  --- Enum defining whether this step is on a drive-on-right or
  drive-on-left route.

- [`GMSNavigationManeuver`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Enums/GMSNavigationManeuver.md.txt)
  --- Enum defining the navigation action to take, such as turn left or
  turn right.

Shown below are example event listeners for the `didChangeNavInfo` event:

### Swift

```c++
  // ViewController.swift
  class SomeViewController: UIViewController {
    ...
    mapView.navigator?.add(self);
    ...
  }

  extension SomeViewController: GMSNavigatorListener {
    func navigator(_ navigator: GMSNavigator,
                   didUpdateNavInfo navInfo: GMSNavigationNavInfo) {

      // Get the current step information
      if navInfo.navState == .enroute {
        if let currentStep = navInfo.currentStep {
          ...
          roadNameLabel.text = currentStep.simpleRoadName
          ...
        }
      }
    }
  }
```

### Objective-C

```c++
  // ViewController.h
  @interface SomeViewController () <GMSNavigatorListener>

  @end

  // ViewController.m
  @implementation SomeViewController
  // Some initialization code.
  ... {
    ...
    [_mapView.navigator addListener:self];
    ...
  }

  #pragma mark GMSNavigatorListener
  - (void)navigator:(GMSNavigator *)navigator didUpdateNavInfo:(GMSNavigationNavInfo *)navInfo {
    // Get the current step information
    if (navInfo.navState == GMSNavigationNavStateEnroute) {
      GMSNavigationStepInfo *currentStep = navInfo.currentStep;
      if (currentStep) {
        ...
        roadNameLabel.text = currentStep.simpleRoadName;
        ...
      }
    }
    ...
  }
```

## Navigation states

Use `navState` property of [`GMSNavigationNavInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationNavInfo.md.txt)
to get the current state of navigation, which is one of the following:

- **Enroute** - The `GMSNavigationNavStateEnroute` state means that guided
  navigation is active and the user is on the provided route.
  Information about the current upcoming maneuver step is available.

- **Rerouting** - `GMSNavigationNavStateRerouting` means that navigation is in
  progress, but the navigator is looking for a new route. The upcoming
  maneuver step is not available, because there's no new route yet.

- **Stopped** - `GMSNavigationNavStateStopped` means navigation has ended. For
  example, navigation stops when the user exits navigation in the app. In the
  sample app, a `GMSNavigationNavStateStopped` state clears the navigation
  info display to prevent lingering step instructions from being displayed.

## Lane guidance

The Navigation SDK represents lanes in the navigation turn card as
`GMSNavigationLane` and `GMSNavigationLaneDirection` data objects. A
`GMSNavigationLane` object represents a specific lane during navigation and has
a list of `GMSNavigationLaneDirection` objects that describe all the turns that
can be made from this lane.

The recommended direction a driver should take in a lane is marked using the
`recommended` field.

![](https://developers.google.com/static/maps/documentation/navigation/ios-sdk/images/lanes-with-recommended.png)

### Lane guidance example

The following snippet illustrates the data representation of the lanes displayed
in the preceding screenshot.

```java
// Lane 1
GMSNavigationLaneDirections =
  [{/*GMSNavigationLaneShape=*/
GMSNavigationLaneShapeNormalLeft, /*recommended=*/ true}]

// Lane 2
GMSNavigationLaneDirections =
  [{/*GMSNavigationLaneShape=*/
GMSNavigationLaneShapeNormalLeft, /*recommended=*/ true}]

// Lane 3
GMSNavigationLaneDirections =
  [{/*GMSNavigationLaneShape=*/
GMSNavigationLaneShapeStraight, /*recommended=*/ false}]

// Lane 4
GMSNavigationLaneDirections =
  [{/*GMSNavigationLaneShape=*/
GMSNavigationLaneShapeStraight, /*recommended=*/ false},
{/*GMSNavigationLaneShape=*/ GMSNavigationLaneShapeNormalRight, /*recommended=*/ false}]
```

### Lane guidance images

The Navigation SDK supports generation of lane images for each navigation step
as conveyed by `GMSNavigationStepInfo`. These icons fit [CarPlay's image sizing
guidance](https://developer.apple.com/design/human-interface-guidelines/carplay#Icons-and-images).

### Swift

```swift
let currentStepInfo = navInfo.currentStep

let options = GMSNavigationStepImageOptions()
options.maneuverImageSize = .square96
options.screenMetrics = UIScreen.mainScreen

let maneuverImage = currentStepinfo.maneuverImage(options: options)
      
```

### Objective-C

```objective-c
GMSNavigationStepInfo *stepInfo = navInfo.currentStep;

GMSNavigationStepImageOptions *options = [[GMSNavigationStepImageOptions alloc] init];
options.maneuverImageSize = GMSNavigationManeuverImageSizeSquare96;
options.screenMetrics = UIScreen.mainScreen;

UIImage* maneuverImage = [stepInfo maneuverImageWithOptions:options];
      
```

## Creating icons for maneuvers

![An icon for a maneuver](https://developers.google.com/static/maps/documentation/navigation/ios-sdk/images/creating_icons.png)

The [`GMSNavigationManeuver`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Enums/GMSNavigationManeuver.md.txt)
enum defines each possible maneuver that could occur while navigating, and you
can get the maneuver for a given step from the `maneuver` property of
[`GMSNavigationStepInfo`](https://developers.google.com/maps/documentation/navigation/ios-sdk/reference/objc/Classes/GMSNavigationStepInfo.md.txt).

You must create maneuver icons and pair them with their associated maneuvers.
For some maneuvers, you can set up a one-to-one mapping to an icon, such as
`GMSNavigationManeuverDestinationLeft` and
`GMSNavigationManeuverDestinationRight`. However, since some maneuvers share
characteristics with other maneuvers, you might want to map more than one
maneuver to a single icon. For example `GMSNavigationManeuverTurnLeft` and
`GMSNavigationManeuverOnRampLeft` could both map to the left turn icon.

Some maneuvers contain an additional "Clockwise" or "CounterClockwise" label,
which the SDK determines based on the driving side of a country. For example,
in countries where driving is on the left side of the road, drivers take a
roundabout or U-turn in a clockwise direction, whereas right-side-of-the-road
countries go counterclockwise. The Navigation SDK detects
whether a maneuver occurs in left- or right-side traffic and outputs
the appropriate maneuver. Therefore, your maneuver icon may be different
for a clockwise versus a counterclockwise maneuver.

#### Expand to see examples icons for different maneuvers

| Sample Icon | Turn-By-Turn Maneuvers |
|---|---|
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_depart.png) | `DEPART` `UNKNOWN` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_straight.png) | `STRAIGHT` `ON_RAMP_UNSPECIFIED` `OFF_RAMP_UNSPECIFIED` `NAME_CHANGE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_right.png) | `TURN_RIGHT` `ON_RAMP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_left.png) | `TURN_LEFT` `ON_RAMP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_slight_right.png) | `TURN_SLIGHT_RIGHT` `ON_RAMP_SLIGHT_RIGHT` `OFF_RAMP_SLIGHT_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_slight_left.png) | `TURN_SLIGHT_LEFT` `ON_RAMP_SLIGHT_LEFT` `OFF_RAMP_SLIGHT_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_sharp_right.png) | `TURN_SHARP_RIGHT` `ON_RAMP_SHARP_RIGHT` `OFF_RAMP_SHARP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_sharp_left.png) | `TURN_SHARP_LEFT` `ON_RAMP_SHARP_LEFT` `OFF_RAMP_SHARP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_u_turn_counterclockwise.png) | `TURN_U_TURN_COUNTERCLOCKWISE` `ON_RAMP_U_TURN_COUNTERCLOCKWISE` `OFF_RAMP_U_TURN_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_u_turn_clockwise.png) | `TURN_U_TURN_CLOCKWISE` `ON_RAMP_U_TURN_CLOCKWISE` `OFF_RAMP_U_TURN_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_right_counterclockwise.png) | `ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_right_clockwise.png) | `ROUNDABOUT_SHARP_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_right_counterclockwise.png) | `ROUNDABOUT_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_right_clockwise.png) | `ROUNDABOUT_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_right_counterclockwise.png) | `ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_right_clockwise.png) | `ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_straight_counterclockwise.png) | `ROUNDABOUT_STRAIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_straight_clockwise.png) | `ROUNDABOUT_STRAIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_left_counterclockwise.png) | `ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_left_clockwise.png) | `ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_left_counterclockwise.png) | `ROUNDABOUT_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_left_clockwise.png) | `ROUNDABOUT_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_left_counterclockwise.png) | `ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_left_clockwise.png) | `ROUNDABOUT_SHARP_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_u_turn_counterclockwise.png) | `ROUNDABOUT_U_TURN_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_u_turn_clockwise.png) | `ROUNDABOUT_U_TURN_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_counterclockwise.png) | `ROUNDABOUT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_clockwise.png) | `ROUNDABOUT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_exit_counterclockwise.png) | `ROUNDABOUT_EXIT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_exit_clockwise.png) | `ROUNDABOUT_EXIT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge_right.png) | `MERGE_RIGHT` `OFF_RAMP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge_left.png) | `MERGE_LEFT` `OFF_RAMP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_fork_right.png) | `FORK_RIGHT` `TURN_KEEP_RIGHT` `ON_RAMP_KEEP_RIGHT` `OFF_RAMP_KEEP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_fork_left.png) | `FORK_LEFT` `TURN_KEEP_LEFT` `ON_RAMP_KEEP_LEFT` `OFF_RAMP_KEEP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge.png) | `MERGE_UNSPECIFIED` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination.png) | `DESTINATION` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination_right.png) | `DESTINATION_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination_left.png) | `DESTINATION_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_ferry_boat.png) | `FERRY_BOAT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_ferry_train.png) | `FERRY_TRAIN` |

## Use generated icons

The Navigation SDK supports generation of maneuver icons for a given
`GMSNavigationStepInfo`. These icons fit [CarPlay image sizing
guidance](https://developer.apple.com/design/human-interface-guidelines/carplay#Icons-and-images).

### Swift

```swift
let currentStepInfo = navInfo.currentStep

let options = GMSNavigationStepImageOptions()
options.maneuverImageSize = .square96
options.screenMetrics = UIScreen.mainScreen

let maneuverImage = currentStepinfo.maneuverImage(options: options)
      
```

### Objective-C

```objective-c
GMSNavigationStepInfo *stepInfo = navInfo.currentStep;

GMSNavigationStepImageOptions *options = [[GMSNavigationStepImageOptions alloc] init];
options.maneuverImageSize = GMSNavigationManeuverImageSizeSquare96;
options.screenMetrics = UIScreen.mainScreen;

UIImage* maneuverImage = [stepInfo maneuverImageWithOptions:options];
      
```