Skip to main content

Search Along Route

Last updated: April 24, 2026 | 5 minutes read

This example demonstrates how to use GEMKit in a UIKit application to calculate a car route, search for landmarks along it using SearchContext, and display the results as grouped Highlights on the map.

Check the full implementation on GitHub.

info

SearchContext settings and parameters showcased in the other examples, such as category and query, can also be applied in this scenario to further refine the search results.

Route Calculated
Search Along Route Results

Map View and Route Display

MapViewController is embedded full-screen with edge insets to leave room for route summary bubbles. The delegate is set so route selection events can promote a route to main. Two navigation bar buttons trigger route calculation and clearing:

ViewController.swiftView on GitHub
func createMapView() {

self.mapViewController = MapViewController.init()
self.mapViewController!.delegate = self
self.mapViewController!.view.backgroundColor = UIColor.systemBackground

self.addChild(self.mapViewController!)
self.view.addSubview(self.mapViewController!.view)
self.mapViewController!.didMove(toParent: self)

self.mapViewController!.setEdgeAreaInsets(UIEdgeInsets(top: 30, left: 40, bottom: 30, right: 40))

self.mapViewController?.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.mapViewController!.view.topAnchor.constraint(equalTo: self.view.topAnchor),
self.mapViewController!.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
self.mapViewController!.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
self.mapViewController!.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])
}

// MARK: - MapViewControllerDelegate

func mapViewController(_ mapViewController: MapViewController, didSelectRoute route: RouteObject) {

self.mainRoute = route

mapViewController.setMainRoute(route)
}

Calculating the Route

routeButtonAction lazily creates a NavigationContext with car preferences on first tap, then calls calculateRoute(withWaypoints:completionHandler:) with San Francisco and San Jose as waypoints. On completion, routes are presented on the map:

ViewController.swiftView on GitHub
@objc func routeButtonAction(item: UIBarButtonItem) {

if self.navigationContext == nil {

let preferences = RoutePreferencesObject.init()
preferences.setTransportMode(.car)
preferences.setRouteType(.fastest)
preferences.setAvoidUnpavedRoads(true)

self.navigationContext = NavigationContext.init(preferences: preferences)
self.navigationContext?.delegate = self
}

let waypoints = [
LandmarkObject.landmark(
withName: "San Francisco", location: CoordinatesObject.coordinates(withLatitude: 37.77903, longitude: -122.41991)),
LandmarkObject.landmark(
withName: "San Jose", location: CoordinatesObject.coordinates(withLatitude: 37.33619, longitude: -121.89058))
]

item.isEnabled = false

self.navigationContext?
.calculateRoute(
withWaypoints: waypoints,
completionHandler: { [weak self] (results: [RouteObject]) in

guard let strongSelf = self else { return }

strongSelf.routeResults = results

if !results.isEmpty {

strongSelf.mainRoute = results.first
strongSelf.addSearch()

strongSelf.mapViewController?.presentRoutes(results, withTraffic: nil, showSummary: true, animationDuration: 1000)
}

item.isEnabled = true
})
}

Searching Along the Route

searchButton lazily initialises a SearchContext with a maximum of 40 matches, then calls searchAlong(withRoute:query:) using the current main route. Results are rendered on the map as grouped highlights via presentHighlights(_:settings:highlightId:):

ViewController.swiftView on GitHub
@objc func searchButton() {

guard let mainRoute = self.mainRoute else { return }

if self.searchContext == nil {

self.searchContext = SearchContext.init()
self.searchContext?.setMaxMatches(40)
self.searchContext?.setSearchMapPOIs(true)
self.searchContext?.setSearchAddresses(true)
}

self.searchContext!
.searchAlong(withRoute: mainRoute, query: "Gas station") { [weak self] (results: [LandmarkObject]) in

guard let strongSelf = self else { return }

let settings = HighlightRenderSettings()
settings.imageSize = 7
settings.options = Int32(HighlightOption.group.rawValue)

strongSelf.mapViewController?.presentHighlights(results, settings: settings, highlightId: strongSelf.defaultHighlightId)
}
}