Skip to main content

iOS Native - Navigation information

The NavigationInfo struct contains all information about the user's progress along the itinerary, including the current leg and step information. This object allows you to get distance and time measurements, previous and next steps, and more.

The NavigationInfoHandler helps to get updated information about the user’s progress along the itinerary on request by providing an updated NavigationInfo struct.

Navigation information is calculated according to CoreConstants.userLocationProjectionOnItineraryEnabled constant.

  • If this constant is enabled, the origin and user projection distances will not be included in the total navigation distance, since these parts are not visible to the user.

  • If this constant is disabled, the origin and user projection distance will be included in the total navigation distance, since these parts are visible to the user. Thus, in this case, the total itinerary distance is not equal to the distance traveled + distance remaining.

Below are code samples showing how to get NavigationInfo using only WemapCoreSDK or WemapMapSDK.

WemapCoreSDK

import RxCocoa
import RxSwift
import UIKit
import WemapCoreSDK

class ViewController: UIViewController {

private let disposeBag = DisposeBag()
private let service = ServiceFactory.getItineraryService()
private let infoHandler = ManagerFactory.getNavigationInfoHandler()
private var itinerary: Itinerary?

override func viewDidLoad() {
super.viewDidLoad()
computeItineraries()
}

private func computeItineraries() {

let origin = Coordinate(latitude: 43.610628, longitude: 3.876654)
let destination = Coordinate(latitude: 43.609011, longitude: 3.917091)

let parameters = ItineraryParameters(origin: origin, destination: destination, travelMode: .bike(preference: .safest))

service
.itineraries(parameters: parameters)
.subscribe(
onSuccess: { [unowned self] response in
debugPrint("response - \(response)")
setItinerary(response.itineraries.first!)
}, onFailure: {
debugPrint("error - \($0)")
}
)
.disposed(by: disposeBag)
}

private func setItinerary(_ itinerary: Itinerary) {
self.itinerary = itinerary
infoHandler.itinerary = itinerary

// request for an update of the navigation information with a certain time interval
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { [unowned self] in
getNavigationInfo(.init(latitude: 43.610107, longitude: 3.891805))
}
}

private func getNavigationInfo(_ userPosition: Coordinate) {
let info = infoHandler.getNavigationInfo(userPosition: userPosition)
debugPrint("navigation info - \(String(describing: info))")
}
}

WemapMapSDK

In WemapMapSDK this logic is controlled by MapNavigationManaging protocol, which you can access directly from the map using mapView.navigationManager as shown below.

NavigationManager observes the user’s progress along the itinerary and constantly calls NavigationManagerDelegate.navigationManager(_: NavigationManager, didUpdateNavigationInfo info: NavigationInfo) method with the updated NavigationInfo struct.

You can set NavigationInfo update time interval using mapView.navigationManager.infoUpdatesTimeInterval = .seconds(2).

import MapLibre
import RxSwift
import UIKit
import WemapCoreSDK
import WemapMapSDK

class NavigationInfoViewController: UIViewController {

private var mapView: MapView!
private let disposeBag = DisposeBag()

override func viewDidLoad() {
super.viewDidLoad()

WemapMap.shared
.getMapData(mapID: 19158, token: "GUHTU6TYAWWQHUSR5Z5JZNMXX")
.subscribe(onSuccess: { [self] mapData in

mapView = MapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.mapDelegate = self
mapView.mapData = mapData

view.addSubview(mapView)

}, onFailure: {
debugPrint("Failed to get map data with error - \($0)")
})
.disposed(by: disposeBag)
}

private func startNavigation() {
let origin = Coordinate(latitude: 43.610628, longitude: 3.876654)
let destination = Coordinate(latitude: 43.609011, longitude: 3.917091)

mapView.navigationManager
.startNavigation(origin: origin, destination: destination)
.subscribe(
onSuccess: { _ in
debugPrint("Successfully started navigation from: \(origin) to: \(destination)")
},
onFailure: { error in
debugPrint("Failed to start navigation from \(origin) to: \(destination) with error: \(error)")
}
).disposed(by: disposeBag)
}
}

extension NavigationInfoViewController: MapViewDelegate {

func mapViewLoaded(_ mapView: MapView, style _: MLNStyle, data _: MapData) {
mapView.navigationManager.delegate = self
mapView.navigationManager.infoUpdatesTimeInterval = .seconds(2) // default is .seconds(1)
mapView.userTrackingMode = .follow
startNavigation()
}
}

extension NavigationInfoViewController: NavigationManagerDelegate {

func navigationManager(_: NavigationManager, didUpdateNavigationInfo info: NavigationInfo) {
debugPrint("Navigation info updated - \(info)")
}
}

Examples

You can find additional examples for the WemapSDKs on GitHub. Clone the repository and run the example application following the instructions in the README.