Skip to main content

Public Transit Route Instructions

Last updated: June 10, 2026 | 2 minutes read

This example demonstrates how to use GEMKit in a UIKit application to calculate a public transit route and display a detailed step-by-step breakdown of each transit segment, including departure times, line colours, and walking legs.

Check the full implementation on GitHub.

Public Transit Route Instructions

UI and Map Integration​

The view controller calculates the route and stores the first result. A list-button in the navigation bar launches the instructions screen:

ViewController.swiftView on GitHub
class ViewController: UIViewController, UISearchBarDelegate {

var mapViewController: MapViewController?
var navigationContext: NavigationContext?
var mainRoute: RouteObject?

override func viewDidLoad() {
super.viewDidLoad()

self.title = "Public Transit"
self.navigationItem.largeTitleDisplayMode = .never

self.createMapView()
self.mapViewController!.startRender()
self.addRouteButton()
}

@objc func routeDescription(item: UIBarButtonItem) {

if let route = self.mainRoute {

let viewController = PTRouteDescriptionViewController.init(route: route)
self.navigationController?.pushViewController(viewController, animated: true)
}
}

Building the Instructions Model​

PTRouteDescriptionViewController iterates the route's segments, casting each to PTRouteSegmentObject to access transit-specific properties such as departure time and line colour. Walking legs are handled separately:

PTRouteDescriptionViewController.swiftView on GitHub
func prepareModelData() {

guard self.route != nil else { return }

let segmentList = self.route!.getSegments()

for segment in segmentList {

guard let segmentPT = segment as? PTRouteSegmentObject else { continue }
guard segmentPT.isSignificant() else { continue }

let section = ModelDataSection.init()
section.area = segment.getGeographicArea()

if segment.isCommon() {

let t1 = segmentPT.getDepartureTimeFormatted()
let t2 = segmentPT.getDepartureTimeUnitFormatted()

let transitType = segmentPT.getTransitType()
var image = UIImage.init(systemName: "tram")

if transitType == .bus {
image = UIImage.init(systemName: "bus")
} else if transitType == .underground {
image = UIImage.init(systemName: "tram.tunnel.fill")
}

section.departureTime = "Departure: " + t1 + t2
section.image = image
section.color = segmentPT.getLineColor().withAlphaComponent(0.4)

} else {

section.image = UIImage.init(systemName: "figure.walk")

let d1 = segment.getTimeDistance()!.getTotalDistanceFormatted()
let d2 = segment.getTimeDistance()!.getTotalDistanceUnitFormatted()
let t1 = segment.getTimeDistance()!.getTotalTimeFormatted()
let t2 = segment.getTimeDistance()!.getTotalTimeUnitFormatted()

section.departureTime = d1 + d2 + " (" + t1 + t2 + ")"
}

for routeInstruction in segment.getInstructions() {

let item = ModelDataItem.init()
item.routeInstruction = routeInstruction
section.items.append(item)
}

self.modelData.append(section)
}
}