Use MKLocalSearch to search for locations on a map

ios, mapkit, mklocalsearch, mkmapview, objective-c

Solution

The API for `MKLocalSearch` is fairly easy to understand. At its most basic, you

- `alloc-init` an `MKLocalSearchRequest`

- Set its `naturalLanguageQuery` to some search term

- Use the search request to initialize an `MKLocalSearch` object

- Tell the local search to start, passing it a completion handler

- Do something with the array of `MKMapItem` objects in the response

Search for Cafes:

// Create a search request with a string 
MKLocalSearchRequest *searchRequest = [[MKLocalSearchRequest alloc] init];
[searchRequest setNaturalLanguageQuery:@"Cafe"];

// Create the local search to perform the search
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:searchRequest];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
    if (!error) {
        for (MKMapItem *mapItem in [response mapItems]) {
            NSLog(@"Name: %@, Placemark title: %@", [mapItem name], [[mapItem placemark] title]);
        }
    } else {
        NSLog(@"Search Request Error: %@", [error localizedDescription]);
    }
}];

You can specify a region for the search like this:

// Search for Cafes in Paris 
MKLocalSearchRequest *searchRequest = [[MKLocalSearchRequest alloc] init];
[searchRequest setNaturalLanguageQuery:@"Cafe"];
CLLocationCoordinate2D parisCenter = CLLocationCoordinate2DMake(48.8566667, 2.3509871);
MKCoordinateRegion parisRegion = MKCoordinateRegionMakeWithDistance(parisCenter, 15000, 15000);
[searchRequest setRegion:parisRegion];

You can also take the region from an `MKMapView` that the user has zoomed into. This will give better results:

[searchRequest setRegion:self.mapView.region];

The response object, an `MKLocalSearchResponse`, contains an array of `MKMapItem` objects (`mapItems`) and an `MKCoordinateRegion` called `boundingRegion`, which is a region that contains all the results. You can use it to set a map view to show all results:

[self.mapView setRegion:response.boundingRegion];

The array of `MKMapItem` objects can't be placed on a map (they're used for sending to the Maps app) but each contains a `placemark` property which can be added to a map:

[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
    if (!error) {
        for (MKMapItem *mapItem in [response mapItems]) {
            NSLog(@"Name: %@, MKAnnotation title: %@", [mapItem name], [[mapItem placemark] title]);
            NSLog(@"Coordinate: %f %f", [[mapItem placemark] coordinate].latitude, [[mapItem placemark] coordinate].longitude);
            // Should use a weak copy of self
            [self.mapView addAnnotation:[mapItem placemark]];
        }
    } else {
        NSLog(@"Search Request Error: %@", [error localizedDescription]);
    }
}];

Search for Dublin places a pin on the map view and logs:

Name: Dublin, Co. Dublin, MKAnnotation title: Dublin, Co. Dublin, Ireland
Coordinate: 53.344104 -6.267494

There are a load of extra details in the returned objects, especially if you search for businesses. Here are a few:

[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
    if (!error) {
        NSLog(@"Results: %@", [response mapItems]);
        MKMapItem *mapItem = [[response mapItems] objectAtIndex:0];
        NSLog(@"Name:%@ Phone:%@ URL:%@", [mapItem name], [mapItem phoneNumber], [mapItem url]);
        NSLog(@"Placemark: %@", [mapItem placemark]);
        MKPlacemark *placemark = [mapItem placemark];
        NSLog(@"Placemark Address: %@", [placemark addressDictionary]);
        MKCoordinateRegion boundingRegion = [response boundingRegion];
        NSLog(@"Bounds: %f %f", boundingRegion.span.latitudeDelta, boundingRegion.span.longitudeDelta);
    }

Problem

I want to use `MKLocalSearch` for searching in a Map. This functionality is available in iOS 6.1+. Does anybody know how to use this or can anybody give an example of how to use an `MKLocalSearch`? MKLocalSearchResponse documentation

Original source