Enabling Search

To support searches based on user-entered queries, Map Kit provides the MKLocalSearch API. Apps can use this API to perform searches for locations that users describe by name, address, or type, such as coffee or theater.

Although local search and geocoding are similar, they support different use cases. Use geocoding when you want to convert between map coordinates and a structured address, such as an Address Book address. Use local search when you want to find a set of locations that match the user’s input.

To search for a location that matches the query a user types into a search field:

  1. Create an MKLocalSearchRequest object and specify a string that contains the user’s natural-language query.

    (Optional) Define a geographical region to narrow the search results. It’s recommended that you define a region to ensure that the user gets relevant results.

  2. Create an MKLocalSearch object and initialize it with the search request you created in step 1.

  3. Start the search by calling startWithCompletionHandler: and specifying a completion handler block to process the results.

Each MKLocalSearch object performs only one search; if you want to perform multiple searches, you have to define multiple search requests and use them to create multiple search objects. Because the search is performed asynchronously, you can create and begin multiple searches in parallel and handle the results as they arrive.

The results of a local search are provided as a set of MKMapItem objects. Each map item object contains the following attributes:

Listing 8-1 shows one way to create a search request, initiate a local search, and display the results as annotations on a map.

Listing 8-1  Searching for locations that match the user’s input

// Create and initialize a search request object.
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = query;
request.region = self.map.region;
 
// Create and initialize a search object.
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
 
// Start the search and display the results as annotations on the map.
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
{
   NSMutableArray *placemarks = [NSMutableArray array];
   for (MKMapItem *item in response.mapItems) {
      [placemarks addObject:item.placemark];
   }
   [self.map removeAnnotations:[self.map annotations]];
   [self.map showAnnotations:placemarks animated:NO];
}];