This tutorial shows how to use the TomTom Maps SDK for iOS to create an application that helps a
user find points of interest along a planned route. The application is written in Objective-C and
Swift language. If you are interested in another example, please check
the Time to leave
tutorial.
It shows how to use:
The TomTom Map SDK module to display a map, including markers with custom icons and balloons.
The TomTom Routing SDK module to plan routes with and without waypoints.
The TomTom Search SDK module to search for points of interest (POIs) and to geocode map positions.
An end user can start interacting with the application by planning a route with departure and
destination points:
One long press on the map sets a departure point.
A second long press sets a destination point and draws a route between those two points on the
map.
When the route is visible on the map, the user can type a POI name or category into a search field
or click on any of the predefined POI category buttons (gas station, restaurant, ATM). The map
displays markers for POIs that match the user's request. The user can add one of the displayed POIs
to their planned route by tapping the marker on the map and choosing the "Add to my route" button
inside the marker balloon that is then displayed. The route is recalculated and redrawn to include
the selected point.
Prerequisites
Make sure that the CocoaPods dependency manager is installed on your
computer: https://cocoapods.org.
Create a new App project named SearchAlongARoute.. Choose either Objective-C or Swift and
make sure that Storyboard is selected.
Go to the console and create a pod file by executing a pod init command.
Copy and paste SDK module dependencies into the newly created Podfile:
1pod 'TomTomOnlineSDKMaps', ‘2.4.713’
2pod 'TomTomOnlineSDKSearch', ‘2.4.713’
3pod 'TomTomOnlineSDKRouting', ‘2.4.713’
4pod 'TomTomOnlineSDKMapsUIExtensions', ‘2.4.713’
Install the SDK modules by typing pod install from the console. After this is finished close
your project and open *.xcworkspace file with XCode. For more details about this step, please
see the downloads section.
If you don't have an API key visit
a How to get a TomTom API key site and
create one. The key will be used later in the code.
Map initialization
To initialize a TomTom map, import the TomTomOnlineSDKMaps module into your project file and add a
placeholder for the new API key. Paste your key in the YOUR_API_KEY placeholder.
The TomTom map handles zooming, panning, rotating and double tapping gestures. In this application
you need to add additional map interactions including location handling, long map press events,
drawing routes and markers.
Now add import statements inside the ViewController file:
Your ViewController class must conform to the protocols:
TTMapViewDelegate
TTAnnotationDelegate
TTAlongRouteSearchDelegate
Add an initTomTomServices method to the ViewController class where the Map Display API modules
are initialized. At the same time, add an initUIViews method where User Interface (UI) elements
are initialized. Move the map initialization code in the initTomTomServices method. Once the map
view is ready to be used the onMapReady method is called, in which you need to enable showing user
current location and enable clustering annotations.
Initialize required fields and services inside the initTomTomServices method. Your **
ViewController** class is used here as a delegate receiving an event notification from the TomTom
Map, Routing and Search services.
Initialize an icon for a departure map annotation inside the initUIViews method.You also need to
add an icon named ic_map_route_departure to the Assets.xcassets directory.
The didLongPress function calls a reverseGeocoder's reverseGeocoderWithQuery method. This method
checks if a road can be found in the place where a long press is registered on the map.
If the reverse geocoding call is successful and contains valid results, the effect of the long press
depends on context:
The first long press on the map sets the departurePosition object.
A second long press sets the destinationPosition object and draws a route on the map.
A third long press removes any destination and departure markers and the route from the map.
Next add functions to send a route request to the Routing API and to draw a route from the response
on the map.
Now you can draw the route on the map by using long presses in chosen locations.
Searching for POIs along the route
Modify the Main.storyboard file by adding a SearchBar control. Add constraints to the SearchBar
control to make sure that it will be displayed correctly on all of the devices.
A bottomConstraint property is adjusted with the size of the keyboard shown on the phone screen
when the user starts typing inside the SearchBar. A keyboardShown property is used to store
information if keyboard is currently visible.
Make sure that the bottomConstraint property field is connected with a SearchBar bottom constraint
from the Main.storyboard file.
Next add an initKeyboardNotificationEvents method where keyboard events are assigned to methods
executed whenever a specific event is triggered.
Methods keyboardDidShow and keyboardDidHide are used to set the keyboardShown field with a
Boolean value holding information about a current keyboard state. Inside a keyboardWillShow and
a keyboardWillHide methods, the keyboard height is adjusted with the value of a keyboard frame
rectangle height.
Optionally implement a single tap on the map event, where you can hide keyboard if it is visible:
Add a UISearchBarDelegate protocol declaration to the ViewController inside the _
ViewController.m_ file and a SearchBar outlet as property inside. Connect your outlet property with
the SearchBar from the Main.storyboard file.
Designate a current ViewController object as a delegate for the newly added searchBar property by
adding this line inside the initUIViews method:
self.searchBar.delegate = self;
self.searchBar.delegate =self
This will allow you to receive and react to the searchBar event notifications. Implement a
method searchBarSearchButtonClicked to be executed whenever a search bar search button is pressed.
In the next step add implementation of the method executed whenever the search bar button is
clicked.
The searchAlongTheRoute function in this object executes a search query for the provided search
term along the route visible on the map.
Add a completedWithResponse method executed when a response is received from the TomTom search
module. Make sure to declare that your ViewController class conforms to the **
TTAlongRouteSearchDelegate** protocol.
The createAndDisplayMarkerAtPosition method then adds a map marker in the position returned by the
search query, including the name and address of the POI.
Adding custom marker balloons
Add a new User Interface View file named CustomAnnotationView. Open the newly added _
CustomAnnotationView.xib_ file and configure the size of the View component inside this file.
Add labels where a point of interest name and an address can be displayed. Additionally add a button
to include point of interest marker to the route displayed on map.
Select all views and add a layout constraints to align items.
Now create a new Cocoa Touch Class file named CustomAnnotationView as a subclass of UIView. Make sure that your CustomAnnotationView conforms to a TTCalloutView protocol by modifying
a CustomAnnotationView file.
Configure a custom class for the main View component in the CustomViewController.xib file.
Inside the CustomAnnotationView file add a WayPointAddedDelegate protocol with a setWayPoint
method defined inside. The class implementing this protocol receives notifications from a button
click inside the marker balloon. Additionally define properties and methods inside the _
CustomAnnotationView_.
When a class implements the WayPointAddedDelegate protocol it must define a setWayPoint method
which is executed whenever a button inside marker balloon is clicked.
Import CustomAnnotationView.h inside the ViewController.m file.
#import"CustomAnnotationView.h"
Add the WayPointAddedDelegate protocol declaration to the ViewController class and implement
a setWaypoint method
In the last step overwrite default behavior of the viewForSelectedAnnotation method where custom
annotation is created for each point of interest along a route.
Inside the createCustomAnnotation method a CustomAnnotationView object is created, and labels
for this object are populated with the information about a found point of interest. Next this
annotation is displayed for each marker visible on the map.
Now you should have a fully working application where you can:
Display a map.
Create a route between 2 points.
Display points of interest.
Add a single POI to your route.
The additional styling, shortcut buttons, and help screen in the application screenshots are not a
part of this tutorial. You can find them, along with all the icons and images used in this tutorial,
in the application posted
on Github.
Summary
This tutorial explained how to create a sample application that searches for and displays points of
interest(POIs) along a route, then recalculates the route to include one of those POIs.
This application can be extended with other TomTom Maps SDK functions, such as displaying
information about traffic and travel distances.
Happy coding!
Example application
The full application, including additional layout changes and improvements, is visible below. At the
bottom of the screen there are three optional buttons that can be used for quick searches for gas
stations, restaurants, and ATMs. There is also a help button in the top right corner along with a
clear button to remove the route and any markers from the map.