Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use MKLocalSearch to search for locations on a map

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

like image 589
Shehbaz Khan Avatar asked Dec 10 '12 10:12

Shehbaz Khan


1 Answers

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

  1. alloc-init an MKLocalSearchRequest
  2. Set its naturalLanguageQuery to some search term
  3. Use the search request to initialize an MKLocalSearch object
  4. Tell the local search to start, passing it a completion handler
  5. 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);
    }
like image 51
nevan king Avatar answered Nov 09 '22 09:11

nevan king