Sorry, you need to enable JavaScript to visit this website.

Search examples

Have a look at our functional examples to see how easy it is to implement search features with the TomTomOnlineSDKSearch. Speed up development by using our sample code snippets in your app. Try all of this out with the Maps SDK Examples app!

Allow your users to easily search for addresses and POIs (Points of Interest) in a single step. Implement global search or near-me search in your mobile app so that it returns the best search results for your needs. Global search uses the search functionality’s default settings. It doesn’t use the user’s position or other search parameters. A sample use case: You use an app to search for a place. This search should not be limited in any way.

Use the following code snippet in your app to list general search results or display them on the map.

_

let query = TTSearchQueryBuilder.create(withTerm: term)
    .build()
search.search(with: query)
TTSearchQuery *query = [[TTSearchQueryBuilder createWithTerm:term] build];
[self.search searchWithQuery:query];

 

Add the following code snippet to your app to get search results that are geo-biased for a given location in a range specified by a radius.

_

let query = TTSearchQueryBuilder.create(withTerm: term)
    .withPosition(coordinate)
    .build()
search.search(with: query)
TTSearchQuery *query = [[[TTSearchQueryBuilder createWithTerm:term] withPosition:coordinate] build];
[self.search searchWithQuery:query];

 

image

Global address search

image

Near me address search

POI Category tree

POI tree

The POI Categories service endpoint provides the full list of POI categories and subcategories together with their translations and synonyms available in Search API, see POI Categories for more information.

Thanks to that list, you do not have to hardcode categories in your app, as they change dynamically. Once you have the POI category ID, you can use them as a filter (categorySet) in search quires.

Sample use case: You want to display a dynamic list of all available categories and subcategories that can be used for search combined with appropriate filters.

Use the code snippet below in your app to get list of categories.

_

let query = TTPoiCategoriesQueryBuilder.create().build()
poiCategoriesService.request(with: query)
TTPoiCategoriesQuery *query = [[TTPoiCategoriesQueryBuilder create] build];
[_poiCategoriesService requestCategoriesWithQuery:query];

 

image

List of categories.  

Help your users search for specific types of places with Category Search. Sample use case: You are preparing for a long drive and would like to find nearby gas stations.

Use the following code snippet to try this in your app.

_

let query = TTSearchQueryBuilder.create(withTerm: "parking")
    .withCategory(true)
    .withPosition(locationManager.lastLocation!.coordinate)
    .build()
search.search(with: query)
TTSearchQuery *query = [[[[TTSearchQueryBuilder createWithTerm:@"parking"] withCategory:YES] withPosition:self.locationManager.lastLocation.coordinate] build];
[self.search searchWithQuery:query];

  For Category Search we use LowBandwidthSearch as in "Address and POI search". The difference is in the endpoint:

Category search

GET https://<baseURL>/search/<versionNumber>/cS/<category>...

For a complete description go to:

The following code example presents an exemplary application view utilizing Category Search.

image

Address search with category: Parking

image

Address search with category: Gas

Language parameter

Develop an international app that can be used in different languages. Enhance the search functionality with the language parameter so that the search returns results in a specific language. Sample use case: If your mobile device is set to a particular language, you see it in your app as well.

List of the supported languages can be found at Supported Languages.

Use the following code snippet to try this in your app.

_

let query = TTSearchQueryBuilder.create(withTerm: term)
    .withLang(language)
    .build()
search.search(with: query)
TTSearchQuery *query = [[[TTSearchQueryBuilder createWithTerm:term] withLang:language] build];
[self.search searchWithQuery:query];

 

Typeahead parameter

Offer your users search suggestions while they type with the "typeahead" flag. Sample use case: You were recommended a place to visit, but you can’t remember its name. You start searching in your app. After a few letters you see the place you’re looking for!

Use the following code snippet to try this in your app.

_

let query = TTSearchQueryBuilder.create(withTerm: term)
    .withTypeAhead(true)
    .build()
search.search(with: query)
TTSearchQuery *query = [[[TTSearchQueryBuilder createWithTerm:term] withTypeAhead:YES] build];
[self.search searchWithQuery:query];

 

Autocomplete enables you to make a more meaningful search by recognizing entities inside your input and offering them as query terms. Autocomplete will fill in the rest with three different types of results: brands, categories, and plain text. The autocomplete complements the ‘typeahead’ parameter used in Fuzzy search by providing related categories and brands that the user might be looking for. Suggestions could appear after typing the first character, however we recommend using it at least after the third character to improve the user experience.

The following examples demonstrate how it works:

Typed letters Obtained suggestions

sta

statue

Railroad Station

United States

sho

shop

Footwear and Shoe repair

Repair Shop

hospital in Lo

hospital

Lotos

lHospital inc

dealer

Automotive dealer

Car dealer

Autotronik

Sample use case: You would like to buy a bottle of wine, but you don`t know where the closest wine shop is. Thanks to “Categories” suggestions you would be able to find the POIs of an appropriate category. You type “win” in your app, and at the 3rd character the service provides some suggestions like “wine shop” or “winery”.

Sample use case: : You use an app to efficiently search for the POI of a specific brand, e.g., you want to find a TomTom office. The Search Autocomplete will return suggested branded POIs based on only a few characters that you type in. So, when typing "Tom" you can expect "TomTom" as the suggested brand which will make your search result more meaningful.

The Autocomplete endpoint information is available in the Search API. Have a look at the detailed documentation for more information related to the Autocomplete endpoint.

Use the following code to try this in your app:

_

let builder = TTAutocompleteQueryBuilder.create(withTerm: text, withLanguage: "en-GB")
builder.withCountry("NL").withLimit(10)
builder.withPosition(TTCoordinate.AMSTERDAM(), withRadius: 10000)
builder.withResultType(.empty)
let query = builder.build()
TTAutocompleteQueryBuilder *builder = [TTAutocompleteQueryBuilder createWithTerm:text withLanguage:@"en-GB"];
TTAutocompleteQuery *query = [[[[builder withCountry:@"NL"] withLimit:10] withResultType:TTResultEmpty] build];

 

The following screen shots present how Autocomplete’s functionality works.

image

Category and brand suggestions

image

Results on the map

To cancel a pending search request in the object, call:

_

func cancelSearch() {
    self.search.cancel()
}
- (void)cancelSearch {
    [self.search cancel];
}

 

Represents information on when a POI will be open during the next 7 days, starting with the current day in the local time of the POI. It returns a list of strings that represent opening and closing hours in a given format: Response body

Sample use case 1: You are searching for a specific store to visit but you don`t know if it is currently open. Through your app you query opening shop times and the store working hours are displayed on the screen.

Sample use case 2: A company is collating a report about closing hours in a given city area for grocery shops. Using the SDK services all grocery’s shops in a given radius can be queried for closing hours, allowing for statistical analysis and other studies.

The opening hours data are available in the Search API.

Have a look at the detailed documentation for more information related to the POI search and Fuzzy search

That parameter will be used for services where POIs are exposed, including:

  • categorySearch

  • searchAlongRoute

  • geometrySearch

  • fuzzySearch

Include "withOpeningHours" in query builder as shown in the code snippet below.

_

let query = TTSearchQueryBuilder.create(withTerm: "Petrol station")
    .withPosition(TTCoordinate.AMSTERDAM())
    .withLang("en-GB")
    .withOpeningHours(.nextSevenDays)
    .build()
TTSearchQuery *query = [[[[[TTSearchQueryBuilder createWithTerm:@"Petrol station"] withPosition:[TTCoordinate AMSTERDAM]] withLang:@"en-GB"] withOpeningHours:TTOpeningHoursNextSevenDays] build];

Screenshots:

image

Fuzziness parameter

Help your users even more with Fuzzy Search. Use the right fuzziness levels in your app to make it less sensitive to typos. Sample use case: You occasionally make mistakes when typing. Your app still returns the desired search results.

Use the following code snippet to try this in your app.

  • Level 1 uses no spell checking.

  • Level 2 is using normal n-gram spell checking. For example, a query "restrant" can be matched to "restaurant".

  • Level 3 is using sound-like spell checking and shingle spell checking. Sound-like spell checking is for "rstrnt" to "restaurant" matching. Shingle spell checking is for "mountainview" to "mountain view" matching.

  • Level 4 doesn’t add any more spell checking functionality.

The search engine will start looking for a match on the level defined by minFuzzyLevel and will stop searching at the level specified by maxFuzzyLevel.

_

let query = TTSearchQueryBuilder.create(withTerm: term)
    .withMinFuzzyLevel(1)
    .withMaxFuzzyLevel(maxFuzzyLevel)
    .withPosition(locationManager.lastLocation!.coordinate)
    .build()
search.search(with: query)
TTSearchQuery *query = [[[[[TTSearchQueryBuilder createWithTerm:term] withMinFuzzyLevel:1] withMaxFuzzyLevel:maxFuzzyLevel] withPosition:self.locationManager.lastLocation.coordinate] build];
[self.search searchWithQuery:query];

 

Reverse geocoding

Sometimes you need to translate a coordinate into a human-readable street address. This is often used in tracking applications that receive a GPS feed from a device or asset and need to obtain the corresponding address. The Reverse Geocoding endpoint returns the address information described in the Reverse Geocoding API documentation on the Developer Portal. Sample use case: You want to know the address of a place on the map. You press your finger on the map display and address information appears in a balloon on the screen.

Use the following code to try this in your app:

_

let query = TTReverseGeocoderQueryBuilder.create(with: coordinate)
    .build()
reverseGeocoder.reverseGeocoder(with: query)
TTReverseGeocoderQuery *query = [[TTReverseGeocoderQueryBuilder createWithCLLocationCoordinate2D:coordinate] build];
[self.reverseGeocoder reverseGeocoderWithQuery:query];

 

image

Reverse geocoder

Polygons for reverse geocoding

Combine Additional Data Provider queries with Reverse Geocoding queries to obtain extra data about a specific entity Type like:

  • Country

  • CountrySubdivision

  • CountrySecondarySubdivision

  • CountryTertiarySubdivision

  • Municipality

  • MunicipalitySubdivision

  • Neighbourhood

  • PostalCodeArea

Sample use case: You want to display Country or Municipality boundaries.

Use the following code to try this in your app:

Create TTReverseGeocoderQuery with the entityType parameter and use Reverse Geocode search.

_

let query = TTReverseGeocoderQueryBuilder.create(with: coordinate).withEntityType(entityType)
    .build()
reverseGeocoder.reverseGeocoder(with: query)
TTReverseGeocoderQuery *query = [[[TTReverseGeocoderQueryBuilder createWithCLLocationCoordinate2D:coordinate] withEntityType:self.entityType] build];
[self.reverseGeocoder reverseGeocoderWithQuery:query];

 

Get the TTGeometryDataSource object from the Response.

_

guard let address = response.result.addresses.first else { return }
guard let additionalDataSources = address.additionalDataSources else { return }
guard let geometryDataSource = additionalDataSources.geometryDataSource else { return }
- (TTGeometryDataSource *_Nullable)geometryDataSourceFromResponse:(TTReverseGeocoderResponse *)response {
    if (response.result.addresses.firstObject != nil) {
        TTReverseGeocoderFullAddress *addressValue = [TTReverseGeocoderFullAddress alloc];
        addressValue = response.result.addresses.firstObject;
        if (addressValue.additionalDataSources) {
            TTAdditionalDataSources *additionalDataSources = [TTAdditionalDataSources alloc];
            additionalDataSources = addressValue.additionalDataSources;
            if (additionalDataSources.geometryDataSource) {
                return additionalDataSources.geometryDataSource;
            }
        }
    }
    return nil;
}

 

Use the TTAdditionalDataSearchQuery object for sending Requests with the TTGeometryDataSource object supported by the Additional Data API.

_

let query = TTAdditionalDataSearchQueryBuilder.create(with: geometryDataSource)
    .withGeometriesZoom(geometriesZoom)
    .build()
searchAdditionalData.additionalDataSearch(with: query)
if ([self geometryDataSourceFromResponse:response] != nil) {
    TTAdditionalDataSearchQuery *query = [[[TTAdditionalDataSearchQueryBuilder createWithDataSource:[self geometryDataSourceFromResponse:response]] withGeometriesZoom:geometriesZoom] build];
    [_searchAdditionalData additionalDataSearchWithQuery:query];
}

 

Sample views utilizing entities retrieved by combining both services:

image

Boundaries for a selected country

image

Boundaries for a selected municipality

=== Search along the route

Allow your users to search for POIs along a planned route so they can optimally add places to their rides. The Along Route Search endpoint allows you to perform a fuzzy search for POIs along a specified route. This search is constrained by specifying the detour time and limiting the number of results. The minimum number of route points is 2.

Sample use case 1: You are driving from Amsterdam to Haarlem and you would like to find a gasoline/petrol station or EV station to fuel or charge your car during your drive. Sample use case 2: Planning your next trip you would like add a car repair station so you can fix something in your vehicle to drive safely.

Use the following code to display 10 POIs along a route with a maximum detour time of 900 sec:

_

let query = TTAlongRouteSearchQueryBuilder(term: "REPAIR_FACILITY", withRoute: mapRoute, withMaxDetourTime: 900)
    .withLimit(10)
    .build()
alongRouteSearch.search(with: query)
    TTAlongRouteSearchQuery *query = [[[TTAlongRouteSearchQueryBuilder withTerm:@"REPAIR_FACILITY" withRoute:self.mapRoute withMaxDetourTime:900] withLimit:10] build];
    [self.alongRouteSearch searchWithQuery:query];
--
{nbsp}
image

With term "REPAIR_FACILITY"  

image

With term "PETROL_STATION"  

image

With term "ELECTRIC_VEHICLE_STATION"  

Allow your users to perform a free text search inside geometries specified by circlers and/or polygons.

Sample use case: You are planing to visit the area of Amsterdam.  You need to find a parking spot, an ATM, and a grocery store in the Amsterdam city center and/or in the west part of the city.

Use the following code snippet to code this in your app:

_

let query = TTGeometrySearchQueryBuilder.create(withTerm: "Parking", searchShapes: geometryShape)
    .withLimit(30)
    .build()
geometrySearch.search(with: query)
TTGeometrySearchQuery *query = [[[TTGeometrySearchQueryBuilder createWithTerm:@"Parking" searchShapes:self.geometryShape] withLimit:30] build];
[self.geometrySearch searchWithQuery:query];

 

The following code example presents an exemplary application that shows Geometry Search.

image

Geometry search with the term: Parking

image

Geometry search with the term: ATM

Entry points

Allow your users to display entry points using fuzzy search results.

Sample use case: A taxi driver wants to pick up a passenger from a specific entry point at the airport.

Use the following code to try this in your app:

_

for entryPoint in entryPoints {
    let annotation = CustomAnnotation(coordinate: entryPoint.position,
                                      annotationImage: TTAnnotationImage.createPNG(withName: "entry_point")!,
                                      anchor: TTAnnotationAnchor.bottom,
                                      type: TTAnnotationType.focal)
    annotation.title = "Entry point type: \(entryPoint.type!)"
    mapView.annotationManager.add(annotation)
}
mapView.zoomToAllAnnotations()
for (TTEntryPoint *entryPoint in entryPoints) {
    CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithCoordinate:entryPoint.position annotationImage:[TTAnnotationImage createPNGWithName:@"entry_point"] anchor:TTAnnotationAnchorBottom type:TTAnnotationTypeFocal];
    annotation.title = [NSString stringWithFormat:@"Entry point type %@", entryPoint.type];
    [self.mapView.annotationManager addAnnotation:annotation];
}
[self.mapView zoomToAllAnnotations];

 

Sample views utilizing entry points:

image

Entry points for the Amsterdam airport

image

Entry points for the Kalvertoren mall

Additional data

Allow your users to request a set of extra entities, like a city or country outline, previously retrieved from the Search API service. For more information, refer to the Additional Data service documentation.

Sample use case: You want to apply colors to geographic-boundary areas such as countries, cities, or districts.

Use the following code to try this in your app:

_

func search(_: TTSearch, completedWith response: TTSearchResponse) {
    guard let result = response.results.first else {
        return
    }
    guard let additionalData = result.additionalDataSources else {
        return
    }
    guard let geometryData = additionalData.geometryDataSource else {
        return
    }
    let query = TTAdditionalDataSearchQueryBuilder.create(with: geometryData).build()
    searchAdditionalData.additionalDataSearch(with: query)
}
func additionalDataSearch(_: TTAdditionalDataSearch, completedWith response: TTAdditionalDataSearchResponse) {
    progress.hide()
    guard let result = response.results.first else {
        return
    }
    let visitor = PolygonAdditionalDataVisitior()
    result.visitGeoJSONResult(visitor)
    var mapPolygons: [TTPolygon] = []
    for lineString in visitor.lineStrings {
        let mapPolygon = TTPolygon(coordinatesData: lineString, opacity: 0.7, color: TTColor.Red(), colorOutline: TTColor.Red())
        mapPolygons.append(mapPolygon)
        mapView.annotationManager.add(mapPolygon)
    }
    mapView.zoom(toCoordinatesDataCollection: mapPolygons)
}
- (void)search:(TTSearch *)search completedWithResponse:(TTSearchResponse *)response {
    TTSearchResult *result = response.results.firstObject;
    if (!result) {
        return;
    }
    TTAdditionalDataSources *additionalData = result.additionalDataSources;
    if (!additionalData) {
        return;
    }
    TTGeometryDataSource *geometryData = additionalData.geometryDataSource;
    if (!geometryData) {
        return;
    }
    TTAdditionalDataSearchQuery *query = [[TTAdditionalDataSearchQueryBuilder createWithDataSource:geometryData] build];
    [self.searchAdditionalData additionalDataSearchWithQuery:query];
}
- (void)additionalDataSearch:(TTAdditionalDataSearch *)additionalDataSearch completedWithResponse:(TTAdditionalDataSearchResponse *)response {
    [self.progress hide];
    TTAdditionalDataSearchResult *result = response.results.firstObject;
    if (!result) {
        return;
    }
    PolygonAdditionalDataVisitior *visitor = [PolygonAdditionalDataVisitior new];
    [result visitGeoJSONResult:visitor];
    NSMutableArray<TTPolygon *> *mapPolygons = [NSMutableArray new];
    for (TTGeoJSONLineString *lineString in visitor.lineStrings) {
        TTPolygon *mapPolygon = [TTPolygon polygonWithCoordinatesData:lineString opacity:0.7 color:[TTColor Red] colorOutline:[TTColor Red]];
        [mapPolygons addObject:mapPolygon];
        [self.mapView.annotationManager addOverlay:mapPolygon];
    }
    [self.mapView zoomToCoordinatesDataCollection:mapPolygons];
}

 

Sample views utilizing entities retrieved from the Additional Data service:

image

Boundaries for Amsterdam

image

Boundaries for Poland

Allow your users to process synchronous Batch Search calls with the Batch Search service being integrated. When the service receives a Request, it will respond as soon as the batch items are calculated and there will be no possibility to retrieve the results later on.

Supported types of requests

  1. Geometry Search

  2. Fuzzy Search

  3. Reverse Geocoder

Different types of requests can be mixed in one Batch Request. The information about the limit of queries, request processing time, and other details are described in the Batch Search service documentation. An error in one of the Batch Requests causes the whole batch to fail.

Sample use case: You want to simultaneously search for different categories within different locations.

Use the following code to try this in your app:

_

let query1 = TTSearchQueryBuilder.create(withTerm: term)
    .withCategory(true)
    .withPosition(TTCoordinate.AMSTERDAM_CENTER_LOCATION())
    .withLimit(10)
    .build()
let query2 = TTSearchQueryBuilder.create(withTerm: term)
    .withCategory(true)
    .withPosition(TTCoordinate.HAARLEM())
    .withLimit(15)
    .build()
let geometry = TTSearchCircle(center: TTCoordinate.HOOFDDORP(), radius: 4000)
let geometryQuery = TTGeometrySearchQueryBuilder.create(withTerm: term, searchShapes: [geometry])
    .build()
let batchQuery = TTBatchQueryBuilder.createSearchQuery(query1)
    .add(query2)
    .addGeometryQuery(geometryQuery)
    .build()
batchSearch.batchSearch(with: batchQuery)
TTSearchQuery *query1 = [[[[[TTSearchQueryBuilder createWithTerm:term] withCategory:YES] withPosition:[TTCoordinate AMSTERDAM_CENTER_LOCATION]] withLimit:10] build];
TTSearchQuery *query2 = [[[[[TTSearchQueryBuilder createWithTerm:term] withCategory:YES] withPosition:[TTCoordinate HAARLEM]] withLimit:15] build];
TTSearchCircle *geometry = [TTSearchCircle circleWithCenter:[TTCoordinate HOOFDDORP] radius:4000];
TTGeometrySearchQuery *geometryQuery = [[TTGeometrySearchQueryBuilder createWithTerm:term searchShapes:@[ geometry ]] build];
TTBatchQuery *batchQuery = [[[[TTBatchQueryBuilder createSearchQuery:query1] addSearchQuery:query2] addGeometryQuery:geometryQuery] build];
[self.batchSearch batchSearchWithQuery:batchQuery];

 

Sample views utilizing data retrieved using the Batch Search service:

image

Search results for different locations

EV Charging Stations Availability

You can use any of the POI searches including Fuzzy Search, Geometry Search, or Along Route Search (see Search API reference) to find a charging point for your electric car.

The EV charging stations IDs are returned from a search query. You can use this ID to check the real-time availability of EV connector types at the charging station using the Extended Search API – EV Charging Stations Availability endpoint. You can view charging station availability when you want to stop during the drive, or due to an event like the low level of your battery. The EV Charging Stations Availability endpoint provides information about the real-time availability of charging points based on criteria such as charging power, probability of being available, etc.

The Response of an EV Charging Stations Availability Request is grouped by the connector type. You can also specify the connector type in your POI searches including Fuzzy Search, Geometry Search, or Along Route Search by defining [connectorSet] to narrow the results. By doing so, the Response will only return the EV charging stations for the specified connector type. Have a look at the detailed documentation about EV Charging Stations Availability.

Important: The method for an EV Charging Stations Availability query uses more than one API service to only accept and return one Request at a time. First, the method makes an API call to a Search endpoint to retrieve the IDs of n charging stations, and then it makes a call to the Extended Search endpoint to retrieve the availability of these n charging stations. In this case, the method uses multiple API calls. If you make a Request to retrieve n charging station details, separate n Requests will be made.

Sample use case: As an EV driver you want to see the EV POIs around a certain location (e.g., when approaching a destination), so you know what charging stations are available around this place.

Sample use case: You want to see upcoming EV POIs along planned route, such that you always have a quick preview of charging possibilities that are in range, matching your vehicle and preferred energy vendor.

Sample use case: You want to know if an EV POI included in the route doesn’t have any available charging spots (e.g., they are all occupied or otherwise unavailable), and you would like to find an alternative EV POI.

Sample use case: : You are planning to visit the area of Amsterdam. You need to find EV charging stations in the city center in Amsterdam.

Use the following code snippets to try this in your app:

First, create a service:

_

let service = EVChargingStationService(apiKey: Key.Search)
self.service = [[EVChargingStationService alloc] initWithApiKey:Key.Search];

If you want to use Fuzzy Search based on the top-left and bottom-right bounding box locations:

_

service.search(topLeft: TTCoordinate.AMSTERDAM_TOP_LEFT(), bottomRight: TTCoordinate.AMSTERDAM_BOTTOM_RIGHT()) { result, _ in
    guard let result = result else {
        return
    }
    self.search(completedWith: result)
}
__weak SearchChargingStationsViewController *weakSelf = self;
[self.service searchWithTopLeft:[TTCoordinate AMSTERDAM_TOP_LEFT]
                    bottomRight:[TTCoordinate AMSTERDAM_BOTTOM_RIGHT]
                     completion:^(NSArray<ChargingStationDetails *> *_Nullable result, NSError *_Nullable error) {
                       SearchChargingStationsViewController *strongSelf = weakSelf;
                       if (result != NULL && strongSelf != NULL) {
                           [strongSelf searchCompletedWithResult:result];
                       }
                     }];

If you want to use Geometry Search based on a given shape like PolygonShape:

_

let locations = coordinates.map { CLLocation(latitude: $0.latitude, longitude: $0.longitude) }
let polygonShape = PolygonShape(locations: locations)
service.search(shape: [polygonShape]) { result, _ in
    guard let result = result else {
        return
    }
    self.search(completedWith: result)
}
PolygonShape *shape = [[PolygonShape alloc] initWithLocations:locations];
[self.service searchWithShape:@[ shape ]
                   completion:^(NSArray<ChargingStationDetails *> *_Nullable result, NSError *_Nullable error) {
                     SearchChargingStationsViewController *strongSelf = weakSelf;
                     if (result != NULL && strongSelf != NULL) {
                         [strongSelf searchCompletedWithResult:result];
                     }
                   }];

If you want to use Along Route Search you first need to use the TTRoute service. Then, based on the TTFullRoute object, get route location points.

_

let routeLocations = route.coordinatesData().map { CLLocation($0.mkCoordinateValue) }
self?.service.search(route: routeLocations, completion: { chargingStationResult, _ in
    guard let chargingStationResult = chargingStationResult else {
        return
    }
    self?.search(completedWith: chargingStationResult)
})
NSMutableArray<CLLocation *> *routeLocations = [@[] mutableCopy];
for (NSValue *value in route.coordinatesData) {
    CLLocation *location = [[CLLocation alloc] init:[value MKCoordinateValue]];
    [routeLocations addObject:location];
}
__weak SearchChargingStationsViewController *weakSelf = self;
[self.service searchWithRoute:routeLocations
                   completion:^(NSArray<ChargingStationDetails *> *_Nullable result, NSError *_Nullable error) {
                     SearchChargingStationsViewController *strongSelf = weakSelf;
                     if (result != NULL && strongSelf != NULL) {
                         [strongSelf searchCompletedWithResult:result];
                     }
                   }];

Screen shots presenting how the EV Charging Stations Availability endpoint functions:

image

Fuzzy search

image

Geometry search

image

Along the route search

Display Photos and add POI Details

POI Details API allows you to provide more useful information about POIs in your app with additional details. As you can see in the documentation of POI Details service ( Points of Interest Details) the information it provides includes:

  1. Current Rating

  2. Price Range

  3. 5 to 10 most relevant user reviews

  4. Social Media details (Facebook, Instagram and Twitter), if available

  5. The Photo IDs that can be used in order to fetch images related to given POI

This what you need to do to get details of a POI:

  1. Search for a POI using any of the POI-searches including Fuzzy, Geometry, or Along Route Search (see SEARCH API reference ) → The response includes a POI ID for each POI in the results.

  2. Call POI Details with the POI ID for the place you want to get details of → The response include rating, priceRange, socialMedia, photos IDs, or reviews.

  3. Done! You can use these details in your app to provide more information about places.

POI Photos API provides photos of the POI.

This what you need to do to get photos of POIs

  1. Search for a POI using any of the POI-searches including Fuzzy, Geometry, or Along Route Search (see SEARCH API reference) → The response includes a POI ID for each POI in the results.

  2. Call POI Details with the POI ID for the place you want to get photos of → The response includes up to 5 Photos IDs.

  3. Call POI Photos with the Photo ID for the place you want to get photos of.

  4. Done! You can display a photo of the POI you need.

For more details and background have a look at the detailed documentation of POI Photos service

Sample use case: You would like to plan a trip to Amsterdam and find a pleasant hostel and choose a pizza restaurant in your neighborhood. Thanks to POI Details you are provided with information including pricing ranges, ratings, reviews, social media details, contact information. Thanks to POI Photos, you can have a look at photos to feel the atmosphere of the places. Foursquare provide dozens of updates every day, so you can count on accurate, reliable information.

Use the following code snippets to try this in your app:

First, create a service:

_

let searchAPI = TTSearch(key: Key.Search)
self.searchAPI = [[TTSearch alloc] initWithKey:Key.Search];

Then using our Search API obtain POI objects

_

let searchQuery = TTSearchQueryBuilder.create(withTerm: "Restaurant").withPosition(TTCoordinate.AMSTERDAM()).withLimit(200).withOpeningHours(.nextSevenDays).build()
searchAPI.search(with: searchQuery) { [weak self] response, _ in
TTSearchQuery *searchQuery = [[[[[TTSearchQueryBuilder createWithTerm:@"Restaurant"] withPosition:TTCoordinate.AMSTERDAM] withLimit:200] withOpeningHours:TTOpeningHoursNextSevenDays] build];
[self.searchAPI searchWithQuery:searchQuery
               completionHandle:^(TTSearchResponse *_Nullable response, TTResponseError *_Nullable error) {

Then based on additionalDataSources in TTSearchResult you need to find Foursquare datasource and grab it’s ID.

_

guard let dataSourceID = additionalDataSources.poiDetailsDataSources.first(where: { $0.sourceName == "Foursquare" })?.dataSourceID else {
    return
}
for (TTPoiDetailsDataSource *poiDetailsDataSources in additionalData.poiDetailsDataSources) {
    if ([poiDetailsDataSources.sourceName isEqualToString:@"Foursquare"]) {
        dataSourceID = poiDetailsDataSources.dataSourceID;
    }
}

Based on that ID you need to get given data source details:

_

let poiDetailsSpecification = AnnotationPoiDetailsSpecification(poiDetailsID: dataSourceID as String)
poiDetailsAPI.fetchPoiDetails(specification: poiDetailsSpecification) { [weak self] poiDetailsResponse, error in
AnnotationPoiDetailsSpecification *poiDetailsSpecification = [[AnnotationPoiDetailsSpecification alloc] initWithPoiDetailsID:dataSourceID];
[self.poiDetailsAPI fetchPoiDetailsWithSpecification:poiDetailsSpecification
                                          completion:^(PoiDetails *_Nullable poiDetailsResponse, NSError *_Nullable error) {

If you want to get photos of given POI:

_

let photoIdArray = poiDetailsResponse.photos.map { PoiPhoto(photoID: $0.photoID) }
self.poiPhotosAPI.get(photos: photoIdArray) { [weak self] images, error in
[self.poiPhotosAPI getWithPhotos:poiPhotoArray
                      completion:^(NSArray<UIImage *> *_Nullable images, NSError *_Nullable error) {

Important: You shall attribute all results delivered by the Extended Search API Points of Interest Details endpoint and Points of Interest Photos endpoint as being ‘powered by Foursquare'.

Screen shots presenting how the POI Details service works:

image