Listen for navigation events

Use this guide to enable your app to listen and respond to a variety of events that change as a user navigates along a route. This guide does not cover defining a route, only responding to events along a route.


The Navigation SDK for iOS provides you with listeners associated with the location of the user and conditions along the route and important time and distance data. On the view controller of the map, your app needs to adopt the protocols for these listeners: GMSRoadSnappedLocationProviderListener and GMSNavigatorListener.

This list shows the listener methods available for navigation events:

See the code

Declaring conformance to the required protocols

Before implementing the navigation methods, the view controller must adopt the protocols:


class ViewController: UIViewController, GMSNavigatorListener, GMSRoadSnappedLocationProviderListener {


@interface ViewController ()


After adopting the navigation protocols, set the listeners to the view controller. For example, you can add the following code to the viewDidLoad() method.


mapView.navigator?.add(self) mapView.roadSnappedLocationProvider?.add(self)


[_mapView.navigator addListener:self]; [_mapView.roadSnappedLocationProvider addListener:self];

Receiving or stopping location updates

Location updates are required for showing the user's progress on the map.

The location instance exposes the following properties:

Location property Description
altitude Current altitude.
coordinate.latitude Current road-snapped latitude coordinate.
coordinate.longitude Current road-snapped longitude coordinate.
course Current bearing in degrees.
speed Current speed.
timestamp Date/time of current reading.

To receive continuous location updates, call mapView.roadSnappedLocationProvider.startUpdatingLocation , and use the GMSRoadSnappedLocationProviderListener to handle the didUpdateLocation event.

The following example shows calling startUpdatingLocation:




[_mapView.roadSnappedLocationProvider startUpdatingLocation];

The following code creates a GMSRoadSnappedLocationProviderListener that handles the didUpdateLocation event.


func locationProvider(_ locationProvider: GMSRoadSnappedLocationProvider, didUpdate location: CLLocation) { print("Location: (location.description)") }


  • (void)locationProvider:(GMSRoadSnappedLocationProvider *)locationProvider didUpdateLocation:(CLLocation *)location { NSLog(@"Location: %@", location.description); }

To receive location updates when the app is in the background, set allowsBackgroundLocationUpdates to true:


mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = true


_mapView.roadSnappedLocationProvider.allowsBackgroundLocationUpdates = YES;

Detecting arrival events

Your app uses the didArriveAtWaypoint event to detect when a destination has been reached. You can resume guidance and advance to the next waypoint by calling continueToNextDestination(), and then re-enabling guidance. Your app must re-enable guidance after calling continueToNextDestination().

After the app calls continueToNextDestination, the navigator no longer has data about the previous destination. If you want to analyze information about a route leg, you must retrieve this from the navigator prior to calling continueToNextDestination().

The following code example shows a method to handle the didArriveAtWaypoint event:


func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) { print("You have arrived at: (waypoint.title)") mapView.navigator?.continueToNextDestination() mapView.navigator?.isGuidanceActive = true }


  • (void)navigator:(GMSNavigator *)navigator didArriveAtWaypoint:(GMSNavigationWaypoint *)waypoint { NSLog(@"You have arrived at: %@", waypoint.title); [_mapView.navigator continueToNextDestination]; _mapView.navigator.guidanceActive = YES; }

Receiving route change updates

To receive a notification whenever the route is changed, create a method to handle the navigatorDidChangeRoute event. You can access the new route by using the routeLegs and currentRouteLeg properties of GMSNavigator.


func navigatorDidChangeRoute(_ navigator: GMSNavigator) { print("The route has changed.") }


  • (void)navigatorDidChangeRoute:(GMSNavigator *)navigator { NSLog(@"The route has changed."); }

Receiving time to destination updates

To receive continuous time to destination updates, create a method to handle the didUpdateRemainingTime event. The time parameter provides the estimated time, in seconds, until the next destination is reached.


func navigator(_ navigator: GMSNavigator, didUpdateRemainingTime time: TimeInterval) { print("Time to next destination: (time)") }


  • (void)navigator:(GMSNavigator *)navigator didUpdateRemainingTime:(NSTimeInterval)time { NSLog(@"Time to next destination: %f", time); }

To set the minimum change in estimated time to the next destination, set the timeUpdateThreshold property on GMSNavigator. The value is specified in seconds. If this property is not set, the services use a default value of one second.


navigator?.timeUpdateThreshold = 10


navigator.timeUpdateThreshold = 10;

Receiving distance to destination updates

To receive continuous distance to destination updates, create a method to handle the didUpdateRemainingDistance event. The distance parameter provides the estimated distance, in meters, to the next destination.


func navigator(_ navigator: GMSNavigator, didUpdateRemainingDistance distance: CLLocationDistance) { let miles = distance * 0.00062137 print("Distance to next destination: (miles) miles.") }


  • (void)navigator:(GMSNavigator *)navigator didUpdateRemainingDistance:(CLLocationDistance)distance { double miles = distance * 0.00062137; NSLog(@"%@", [NSString stringWithFormat:@"Distance to next destination: %.2f.", miles]); }

To set the minimum change in estimated distance to the next destination, set the distanceUpdateThreshold property on GMSNavigator (value is specified in meters). If this property is not set, the services use a default value of one meter.


navigator?.distanceUpdateThreshold = 100


navigator.distanceUpdateThreshold = 100;

Receiving traffic updates

To receive continuous updates of the traffic flow for the remaining route, create a method to handle the didUpdateDelayCategory event. A call to delayCategoryToNextDestination returns GMSNavigationDelayCategory which provides a value of 0 to 3. Updates to the category are based on the current position of the app user. If traffic data is unavailable, GMSNavigationDelayCategory returns 0. The numbers, 1-3, indicate increasing flow from light to heavy.


func navigator(_ navigator: GMSNavigator, didUpdate delayCategory: GMSNavigationDelayCategory) { print("Traffic flow to next destination: (delayCategory)") }


  • (void)navigator:(GMSNavigator *)navigator didUpdateDelayCategory:(GMSNavigationDelayCategory)delayCategory { NSLog(@"Traffic flow to next destination: %ld", (long)delayCategory); }

The GMSNavigationDelayCategory property exposes the following delay levels:

Delay category Description
GMSNavigationDelayCategoryNoData 0 - Unavailable, no data for traffic or :
the route.
GMSNavigationDelayCategoryHeavy 1 - Heavy.
GMSNavigationDelayCategoryMedium 2 - Medium.
GMSNavigationDelayCategoryLight 3 - Light.

Receiving speeding updates

To receive updates when a driver is exceeding the speed limit, create a method to handle the didUpdateSpeedingPercentage event.


// Listener to handle speeding events. func navigator( _ navigator: GMSNavigator, didUpdateSpeedingPercentage percentageAboveLimit: CGFloat ) { print("Speed is (percentageAboveLimit) above the limit.") }


// Listener to handle speeding events. - (void)navigator:(GMSNavigator *)navigator didUpdateSpeedingPercentage:(CGFloat)percentageAboveLimit { NSLog(@"Speed is %f percent above the limit.", percentageAboveLimit); }

Changing suggested lighting mode

To receive updates for estimated changes in lighting, create a method to handle the didChangeSuggestedLightingMode event.


// Define a listener for suggested changes to lighting mode. func navigator(_ navigator: GMSNavigator, didChangeSuggestedLightingMode lightingMode: GMSNavigationLightingMode) { print("Suggested lighting mode has changed: (String(describing: lightingMode))")

// Make the suggested change. mapView.lightingMode = lightingMode }


// Define a listener for suggested changes to lighting mode. -(void)navigator:(GMSNavigator *)navigator didChangeSuggestedLightingMode: (GMSNavigationLightingMode)lightingMode { NSLog(@"Suggested lighting mode has changed: %ld", (long)lightingMode);

// Make the suggested change. _mapView.lightingMode = lightingMode; }