Search

With MapKit SDK, you can search for map locations and objects by name. For example, you can use the search API to get a list of nearby restaurants, see if there are any gas stations along the route, or find a location based on its exact address. In addition to name search, MapKit SDK offers Geocoder queries. With this feature, you can locate an object's coordinates based on its address, or vice versa — find out an object's address based on its coordinates.

Warning

The search functionality is available in the full version of the MapKit SDK.

Executing a search query

Let's examine the general algorithm for executing a search query with the MapKit SDK:

  1. Create an instance of the MMKSearchManagerType class to use as the entry point to the MapKit SDK search API.

    let searchManager = MMKSearch.sharedInstance().createSearchManager(with: .combined)
    

    When instantiating MMKSearchManager, specify its MMKSearchManagerType, which determines the mode of operation: offline, online, or mixed.

  2. Determine which search query type should be used in your case.

    For example, use the MMKSearchManager.submit(withText:geometry:searchOptions:responseHandler:) method to search for text within a geometry.

  3. Create an instance of the MMKSearchOptions class to set the search parameters for the query.

    Example of parameter values for limiting the search to organizations:

    let searchOptions: MMKSearchOptions = {
        let options = MMKSearchOptions()
        options.searchTypes = .biz
        options.resultPageSize = 32
        return options
    }()
    
  4. Create a new search session using the method from the MMKSearchManager class that corresponds to the search query type you need.

    Example of a search session for finding places to eat, such as cafes and restaurants:

    let session = searchManager.submit(
        withText: "where to eat",
        geometry: MMKVisibleRegionUtils.toPolygon(with: map.visibleRegion),
        searchOptions: searchOptions,
        responseHandler: handleSearchSessionResponse
    )
    
  5. When creating the search session, use the following mechanism to retrieve the search query results.

    Create a handler with type MMKSearchSessionResponseHandler:

    private func handleSearchSessionResponse(response: MMKSearchResponse?, error: Error?) {
        if let error {
            // Handle search error
            return
        }
    
        // Handle search response
    }
    

    Pass this handler method as an argument whenever you call a method for creating a search session.

Search query types

The MapKit SDK offers several search query types, each tailored to specific search scenarios. Queries are organized into the following groups:

Let's examine the main features and differences of each search query type.

This type executes a search based on the text entered by the user.

Text search is very flexible. For example, depending on the entered text, you can search by:

  • Organization name
  • Address
  • Category name (for example, "Restaurants" or "Fitness")
  • Activity (for example, "Where to go for a walk in the evening")
  • Coordinates (for example, (25.1982, 55.272758))

There are two types of methods that can be used to create a text search session:

  1. MMKSearchManager.submit(withText:geometry:searchOptions:responseHandler:): Executes a search based on the query text, looking for objects within a specific geometry on the map: along a polyline, near a point, or inside a boundingBox or polygon.

  2. MMKSearchManager.submit(withText:polyline:geometry:searchOptions:responseHandler:): Searches along a polyline but within a specific boundingBox or polygon. This method is useful for searching along the route section visible within the map viewport. For example, you can use it to search for gas stations located along a route.

When searching along a route, the MapKit SDK sorts the search results based on the distance between the found objects and the passed polyline and returns the closest ones.

Reverse geocoding

Reverse geocoding enables you to get the address or name of the object located at the coordinates specified by the user.

To create a reverse search session, use the MMKSearchManager.submit(with:zoom:searchOptions:responseHandler:) method with the following arguments:

  • point: The point whose coordinates are used in the search.
  • zoom: The current zoom level of the map. It's used to discard objects that are too small at low zoom levels.

Some geo objects on MapKit maps provide a string URI. URI search enables you to search for this type of object. You can retrieve the URI from the geo object's URI metadata.

There are two types of methods for creating a URI search session:

  1. MMKSearchManager.resolveURI(withUri:searchOptions:responseHandler:): Used to search for geo objects by their URI retrieved from the URI metadata.

  2. MMKSearchManager.searchByURI(withUri:searchOptions:responseHandler:): Enables you to find multiple objects by URI. This can be used in Geosuggest searches.

Search parameters

All search query types can take a MMKSearchOptions argument to define the search parameters.

Search parameters include:

  • searchTypes: Type of objects to search for: toponyms, companies, or both.
  • resultPageSize: The number of results per search page.
  • userPosition: Used to calculate the distance between the user and the objects returned by the search.
  • geometry: Returns the geometry of the found object (used when searching for toponyms).
  • disableSpellingCorrection: Turns on the correction of errors in the search query text.
  • filters: Sets filtering parameters for the search query.

Warning

Depending on the search query type, some search parameters may be ignored.

To find out which search parameters are supported for a specific search query type, see the documentation on the MMKSearchManager class search methods.

Search session

The MapKit SDK implements search queries as an asynchronous operation that may require a network request (for example, when performing an online search). All methods for creating search queries contained in the MMKSearchManager class return a MMKSearchSession object that manages the state of the search query.

Example of creating a search session to find restaurants on the map:

searchSession = searchManager.submit(
    withText: "Restaurant",
    geometry: MMKVisibleRegionUtils.toPolygon(with: map.mapRegion),
    searchOptions: {
        let options = MMKSearchOptions()
        options.searchTypes = .biz
        return options
    }(),
    responseHandler: handleSearchSessionResponse
)

Warning

The MMKSearchSession object must be stored on the client app side. Otherwise, the search query may be automatically canceled.

The MMKSearchSession class supports a large number of operations for managing search queries, such as canceling the current query, retrieving the next results page, and enabling the sorting of results for distances to a specific geometry. With the recurring query feature, you can change some parameters of the original query and then execute the query again.

Example of using a MMKSearchSession object to create a recurring query that takes different search geometries:

private var searchSession: MMKSearchSession?

func resubmitAfterMove() {
    let geometry = MMKVisibleRegionUtils.toPolygon(with: map.visibleRegion)
    searchSession?.setSearchAreaWithArea(geometry)
    searchSession?.resubmit(responseHandler: handleSearchSessionResponse)
}

You can use this method in cases such as when the camera position changes after the user swipes the map.

Search results

To retrieve the results of a search query, pass the responseHandler parameter into MMKSearchManager.submit(withText:geometry:searchOptions:responseHandler:) method. This handler will be called once the search query finishes.

MMKSearchSessionResponseHandler takes two parameters:

  1. response: If present, says about a successful search query completion. The value of type MMKSearchResponse contains information about the results of the request.

  2. error: If present, says about an error, occurred while a query execution.

If the request is successful, you can retrieve a MMKSearchResponse object with information about:

Let's take a closer look at the information included in the data on successful query completion.

Geo object collection

You can use the MMKSearchResponse.collection method to get a collection of the found objects. With the MMKGeoObjectCollection.children method, you can get a list of found geo objects.

private func handleSearchSessionResponse(response: MMKSearchResponse?, error: Error?) {
    if let error {
        onSearchError(error: error)
        return
    }

    guard let response,
          let boundingBox = response.metadata.boundingBox else {
        return
    }

    let geoObjects = response.collection.children.compactMap { $0.obj }

    // Process geoObjects collection
}

Geo objects

The MMKGeoObject class is a MapKit SDK entity that provides information about map objects. A geo object can be an organization, a building, or a geographic object like a country, city, or sea.

There are two types of geo objects:

  1. Organizations: Restaurants, beauty salons, government buildings, schools, hospitals, stores, hotels, and other businesses.
  2. Toponyms: Buildings, cities, countries, and various geographic features.

In the context of the search API, geo objects are used as search results. The most commonly used geo object search parameters are:

  • name: Object name.
  • geometry: Contains the coordinates of an organization or the geometry of a toponym.
  • metadataContainer: Used to augment the base geo object with additional metadata.

Different types of geo objects have different types of metadata.

MMKUriObjectMetadata

Using the MMKUriObjectMetadata type, you can get the unique ID of a geo object.

let uri = (
    geoObject.metadataContainer.getItemOf(MMKUriObjectMetadata.self) as? MMKUriObjectMetadata
)?.uris.first

URIs can be used to organize your app's bookmarking feature. When the user adds a favorite location, the app saves the string ID of the associated geo object. When the user wants to return to a saved location, you can perform a URI search to retrieve the geo object and display it on the map.

MMKSearchBusinessObjectMetadata

The MMKSearchBusinessObjectMetadata class includes a wide range of methods that provide different types of information about the organization. MMKSearchBusinessObjectMetadata can only be retrieved from geo objects that are organizations.

let metadata = (
    geoObject.metadataContainer
        .getItemOf(MMKSearchBusinessObjectMetadata.self) as? MMKSearchBusinessObjectMetadata
)
if let metadata {
    // Geo object is a business organization
} else {
    // Not an organization
}

The key data of the MMKSearchBusinessObjectMetadata class include:

  • name: Organization name.
  • address: Organization address.
  • phones: List of the organization's phone numbers.
  • workingHours: Business hours of the organization.
  • features: A list of the organization's features, such as the availability of Wi-Fi or card payment options.

MMKSearchToponymObjectMetadata

You can use the MMKSearchToponymObjectMetadata class to get additional information about a toponym, such as its address or name. MMKSearchToponymObjectMetadata can only be retrieved from geo objects that are toponyms.

Query metadata

Query metadata is represented by the MMKSearchMetadata class, which contains additional information about the search query.

General information includes:

  • found: Approximate number of found objects.
  • displayType: Defines the display type. If the result isn't part of a group, the value is single. In this case, re-executing the query when moving the map is most likely unnecessary. If the result may be part of a group, the value is multiple. In this case, re-executing the query may be necessary when moving the map.
  • boundingBox: The bounding box of the map objects returned by search. You can move the viewport to this geometry to display the search results on the map.
  • sort: The type of sorting applied to the objects in the output. For example, you can sort them by distance from the user.
  • toponym: The result of reverse geocoding, if it was applied.
  • requestText: The query text entered by the user as part of their search.
  • correctedRequestText: requestText with automatic correction applied.
  • requestBoundingBox: The map's bounding box passed when creating the request.

In addition to general information, query metadata contains additional information that depends on the search query type and whether the search was performed for organizations or toponyms:

  • toponym: Contains the geo object with the toponym returned by the search.
  • toponymResultMetadata: Additional information about the toponym search query.
  • businessResultMetadata: Additional information about the organization search query.

Let's take a closer look at the differences between toponymResultMetadata and businessResultMetadata.

MMKSearchToponymResultMetadata

The metadata of toponym search results is represented by the MMKSearchToponymResultMetadata class, which provides the following information:

  • Number of toponyms found.
  • Search mode and accuracy.
  • Coordinates used for reverse geocoding.

MMKSearchBusinessResultMetadata

The MMKSearchBusinessResultMetadata class provides information on the presence of:

  • Search categories in search results.
  • Search chains (the list isn't empty if a chain organization was found for the query).
  • Search filters.