Inspect Route Element for iOS

Last updated:

  1. Developing on the new Arm-based Apple Silicon (M1) Macs requires building and running on a physical iOS device or using an iOS simulator running iOS 13.7, e.g. iPhone 11. This is a temporary limitation in Google Maps SDK for iOS, and as such also a limitation in MapsIndoors, due to the dependency to Google Maps.
  2. Note: Due to a bug in CocoaPods it is necessary to include the post_install hook in your Podfile described in the PodFile post_install wiki.

In this tutorial we will request a route, list the route parts and render these on a Google Map. A MapsIndoors route is made of one or more legs, each containing one or more steps.

We will start by making the controller that renders the route from the input of a route, a leg index and optionally a step index. Start by creating a UIViewController implementation that conforms to MPDirectionsRendererDelegate

class ShowRouteOnMapController: UIViewController, MPDirectionsRendererDelegate {

Setup member variables for ShowRouteOnMapController:

  • An instance of type GMSMapView
  • An instance of type MPMapControl
  • An instance of type MPRoute (the route object)
  • A leg index
  • A step index
var map: GMSMapView? = nil
var mapControl: MPMapControl? = nil
var route:MPRoute? = nil
var leg:Int = -1
var step:Int = -1

Create an initializer for your input parameters

convenience init(_ route:MPRoute, _ leg:Int, _ step:Int) {
self.init(nibName:nil, bundle:nil)
self.route = route
self.leg = leg
self.step = step
}

Setup the Google map and your MPMapControl instance

self.map = GMSMapView.init(frame: CGRect.zero)
self.view = self.map
self.map?.camera = .camera(withLatitude: 57.057964, longitude: 9.9504112, zoom: 20)
self.mapControl = MPMapControl.init(map: self.map!)

Inside viewDidAppear, setup a directions renderer and assign the Google map, route object and leg/step indices. Eventually, call the animate method to make it animate from the start to end of the leg/step

let renderer = MPDirectionsRenderer.init()

renderer.delegate = self
renderer.fitBounds = true

renderer.map = self.map
renderer.route = route

renderer.routeLegIndex = leg
renderer.routeStepIndex = step
renderer.animate(5)

In the floorDidChange delegate method change the floor on your MPMapControl instance

func floorDidChange(_ floor: NSNumber) {
mapControl?.currentFloor = floor
}

See the sample in ShowRouteOnMapController.swift

Create the Controller That Requests the Route, and List the Route in a Table

A MapsIndoors route is made of one or more legs, each containing one or more steps.

Start by creating a UIViewController implementation

class ShowRouteController: UITableViewController {

Add a MPRoute property to the class

var route:MPRoute? = nil

Inside viewDidLoad, setup a directions service, call the directions service and save the route result to your MPRoute property

let directions = MPDirectionsService.init()

let origin = MPPoint.init(lat: 57.057917, lon: 9.950361, zValue:0)
let destination = MPPoint.init(lat: 57.058038, lon: 9.950509, zValue:1)

let directionsQuery = MPDirectionsQuery.init(originPoint: origin!, destination: destination!)

directions.routing(with: directionsQuery) { (route, error) in
self.route = route
self.tableView.reloadData()
}

Override numberOfRowsInSection to return the number of steps in the current leg plus the leg itself

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let leg:MPRouteLeg = route?.legs?[section] as? MPRouteLeg {
return leg.steps!.count + 1
}
return 0
}

Override numberOfSections to return the number of legs

override func numberOfSections(in tableView: UITableView) -> Int {
if let legs = route?.legs?.count {
return legs
}
return 0
}

Override titleForHeaderInSection to return the leg index

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Route Leg \(section)"
}

Override tableView:cellForRowAt to return leg index and step index if applicable

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell.init()

if indexPath.row > 0 {
cell.textLabel?.text = "Show leg \(indexPath.section), step \(indexPath.row - 1)"
} else {
cell.textLabel?.text = "Show leg \(indexPath.section), all steps"
}
cell.accessibilityIdentifier = cell.textLabel?.text

return cell
}

Override tableView:didSelectRowAt to push a new view controller

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = ShowRouteOnMapController.init(route!, indexPath.section, indexPath.row - 1)
navigationController?.pushViewController(vc, animated: true)
}

See the sample in ShowRouteController.swift