Guidance

MMKGuidance contains information on the current guidance session and lets you follow events in guidance mode. Use the MMKNavigation.guidance method to get it.

Track location

By default, MMKNavigation is created in suspended mode, where location isn't tracked and guidance is off. To start tracking the current device location, use resumed mode. That keeps the user's location up to date.

To manage the location tracking mode, use the MMKNavigation.resume() and MMKNavigation.suspend() methods.

Tip

It's a good idea to switch MMKNavigation to suspended mode when you collapse the app and the map and switch it back to resumed when you reopen the app.

We don't recommend switching MMKNavigation to suspended mode for the background guidance scenario.

Start/stop guidance

To start route guidance, use the MMKNavigation.startGuidance(with:) method. It takes the route as its only argument.

To stop guidance, use the matching MMKNavigation.stopGuidance() method.

Note

The number of possible active guidance sessions is limited. There can only be one active guidance session at a time.

Guidance data

Let's look at the main data MMKGuidance provides access to.

  • Current route: MMKGuidance.currentRoute() contains the route where guidance is currently active or the null value if guidance is inactive. In guidance mode, the current route can change, for example, if the user deviates from the route or chooses an alternate route.

  • User location: MMKGuidance.location contains the current user location. That includes the location coordinates, current direction, location precision, guidance speed, and more.

  • Speeding: MMKGuidance.speedLimit and MMKGuidance.speedLimitStatus provide information on the speed limit for the current route section. MMKGuidance.speedLimitsPolicy provides information about speed limits for different areas in the current region (in the city, outside the city, and on highways).

The complete API is available in the MMKGuidance documentation.

Windshield

The MMKNavigationWindshield entity is used to provide information about oncoming maneuvers on the route, road markings and events, speed limits, and road signs.

To access the MMKNavigationWindshield instance, use the MMKGuidance.windshield method.

The MMKNavigationWindshield entity status is defined by the following data:

  • Maneuvers: Using MMKGuidance.Manoeuvres, you can get a list of maneuvers on the route. Each maneuver is described by its position on the route, location, and the MMKDrivingAnnotation instance that contains information about its type.

  • Road markings: MMKGuidance.laneSigns returns a list where each instance contains information about the lane the user must be on. It is characterized by its position on the route and the MMKDrivingLaneSign instance, which defines the road markings type at a road section. The MMKDrivingLaneSign instance contains the list of MMKDrivingLane with information about each separate traffic lane, its direction, type, and possible maneuvers.

  • Road events: Using MMKGuidance.roadEvents, you can get a list of road events on the route as well as information about speed limits.

  • Road signs: The MMKGuidance.directionSigns method returns a list of road signs on the route. For example, a sign that indicates the next route section includes a tunnel or a highway

Using MMKNavigationWindshieldListener, you can follow MMKNavigationWindshield status change events.

You can see an example of how MMKNavigationWindshield can be used for implementing the UI component that displays information about the next maneuver and lane markings in the demo app.

Events

In guidance mode, the guidance status changes constantly. Use the MMKGuidanceListener interface to follow guidance events.

class GuidanceListener: NSObject, MMKGuidanceListener {
    func onLocationChanged() {}
    func onCurrentRouteChanged(with reason: MMKRouteChangeReason) {}
    func onRouteLost() {}
    func onReturnedToRoute() {}
    func onRouteFinished() {}
    func onWayPointReached() {}
    func onStandingStatusChanged() {}
    func onRoadNameChanged() {}
    func onSpeedLimitUpdated() {}
    func onSpeedLimitStatusUpdated() {}
    func onAlternativesChanged() {}
    func onFastestAlternativeChanged() {}
}
let guidanceListener = GuidanceListener()
guidance.addListener(with: guidanceListener)

MMKGuidanceListener lets you follow navigation events (deviation from the route, return to the route, and arrival at intermediate and final stops) and guidance status changes (for the current user location, street name, speed limit information, list of alternatives, and more).

Guidance alternatives

Local alternatives are the alternate routes available in guidance mode. They're recalculated automatically. To follow this event, use the MMKGuidanceListener.onAlternativesChanged() method.

To switch from the current route to an alternate one, use the MMKGuidance.switchToRoute(with:) method.

Faster alternative routes

Route guidance sessions might sometimes last as long as several hours. In these cases, the initially built route might become outdated and less convenient with time. This is relevant for city guidance since the traffic situation might change quite often. NaviKit SDK solves this problem and provides an opportunity to get a faster alternative route.

The MMKGuidance.fastestAlternative method returns information about a faster alternative route, if one exists. Start guidance along such a route to change the current route to a faster one.

Using the MMKGuidanceListener.onFastestAlternativeChanged() handler method, you can follow notifications about changes in the faster route.

Annotations

To set up voice guidance (voice annotations) for the route, use the MMKAnnotator class.

To enable and disable annotations, use the MMKAnnotator.mute() and MMKAnnotator.unmute() methods.

For the annotator to start working, add a MMKSpeaker delegate to it and implement it yourself.

Note

NaviKit SDK doesn't provide MMKSpeaker implementation.

There's an example of MMKSpeaker implementation using the iOS AVSpeechSynthesizer in the demo app.

To change the annotation language, use the MMKNavigation.annotationLanguage method.

Annotations are divided into two types: MMKAnnotatedRoadEvents are related to road events and MMKAnnotatedEvents are related to route warnings. You can manage the amount of activity for specific annotations using the MMKAnnotator.annotatedRoadEvents and MMKAnnotator.annotatedEvents methods.

You can follow MMKAnnotator class events using the MMKAnnotatorListener interface. It notifies you about annotator actions (the type of event that was performed).

Restore status

You can restore the guidance status by serializing/deserializing MMKNavigation.

  1. To do so, serialize MMKNavigation using the MMKNavigationSerialization.serialize(_:) method.

    let serializedNavigation = MMKNavigationSerialization().serialize(navigation)
    
  2. serializedNavigation now contains a navigation copy. You can save it to a disk and later restore it using deserialization.

  3. Using MMKNavigationSerialization.deserialize(_:), create a new navigation instance.

    let navigation = MMKNavigationSerialization().deserialize(serializedNavigation)
    

Before closing the app, you can save MMKNavigation to a disk and restore it when you open the app again later. Because guidance status is in MMKGuidance and guidance is part of MMKNavigation, it'll also be restored, and the last guidance session will continue.

There's an example of how to implement the logic for restoring guidance statuses in the demo app.

Guidance simulation

When developing and testing navigation apps, you may need to check how the guidance scenario works. To do so, use third-party tools for simulating user locations or the ready-made simulation API in NaviKit SDK.

To enable location simulation along a route or in an arbitrary direction, use the MMKLocationSimulator class.

Here's an example of how to implement the guidance simulation manager:

class SimulationManager: NSObject, MMKLocationSimulatorListener {

    // MARK: - Public methods

    func startSimulation(route: MMKDrivingRoute) {
        locationSimulator = MMKMapKit.sharedInstance().createLocationSimulator(withGeometry: route.geometry)

        locationSimulator.subscribeForSimulatorEvents(with: self)
        locationSimulator.speed = 20.0

        MMKMapKit.sharedInstance().setLocationManagerWith(locationSimulator)

        locationSimulator.startSimulation(with: .coarse)
    }

    func resetSimulation() {
        locationSimulator?.unsubscribeFromSimulatorEvents(with: self)
        locationSimulator = nil
        MMKMapKit.sharedInstance().resetLocationManagerToDefault()
    }

    func setSpeed(value: Double) {
        locationSimulator?.speed = speed
    }

    // MARK: - Private properties

    private var locationSimulator: MMKLocationSimulator!
}

The startSimulation method accepts the route for guidance simulation. When you use MMKMapKit.createLocationSimulator(withGeometry:), a new MMKLocationSimulator is created. You need to configure it:

  1. Follow the simulation finish event using MMKLocationSimulatorListener.
  2. Set the movement speed value.
  3. Change the MMKLocationManager implementation to the newly created locationSimulator.
  4. Start the simulation.

The simulation is reset in resetSimulation. With MMKMapKit.resetLocationManagerToDefault(), the location simulation manager changes to the default option, which reads the user's current location.

There's a detailed example of route simulation in the demo app.

Background guidance

Background guidance refers to a guidance session that can continue even after the application is moved to the background.

After the application moves to the background, the iOS system may suspend it to free up resources. For the iOS app to work even when application is in the background, it could track the device location.

To implement background guidance, subscribe to device location changes when the app is moved to the background. After the app is closed, MMKNavigation must stay in resumed mode. That way, the app won't be killed by the iOS system, and voice guidance will work in background mode.

Note

NaviKit SDK does not create a location subscription, so it does not guarantee that the application will work in a background. To implement the background guidance scenario, you need to implement location subscription by yourself.

There's an example of the background guidance service in the demo app.