¿Cómo buscar MKMapView con UISearchBar?

Tengo una aplicación que necesita tener una función de búsqueda similar, como la aplicación “Mapas” de Apple (incluida con iPhone, iPod Touch y iPad).

La característica en cuestión no debería ser algo difícil de hacer, pero realmente no tengo idea de cómo ingresar una Dirección de calle en la barra de búsqueda, y luego obtener coordenadas para esa dirección o algo que pueda ayudarme a mover realmente el mapa y centro en ese lugar.

Es decir, ¿qué tengo que consultar? ¿Apple proporciona un “método API de búsqueda de direcciones”? o necesito usar la API de google maps directamente?

Me encantaría escuchar cómo debería hacerse.

Este quizás sea el método más fácil. Utiliza servidores Apple para geocodificar. A veces, los servidores Apple proporcionan una mejor respuesta que google. Y pronto (en IOS 6.1), los mapas de Google estarán completamente fuera de iOS. Por lo tanto, es bueno si la aplicación permanece dentro de las características proporcionadas por Apple.

-(void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar { [theSearchBar resignFirstResponder]; CLGeocoder *geocoder = [[CLGeocoder alloc] init]; [geocoder geocodeAddressString:theSearchBar.text completionHandler:^(NSArray *placemarks, NSError *error) { //Error checking CLPlacemark *placemark = [placemarks objectAtIndex:0]; MKCoordinateRegion region; region.center.latitude = placemark.region.center.latitude; region.center.longitude = placemark.region.center.longitude; MKCoordinateSpan span; double radius = placemark.region.radius / 1000; // convert to km NSLog(@"[searchBarSearchButtonClicked] Radius is %f", radius); span.latitudeDelta = radius / 112.0; region.span = span; [theMapView setRegion:region animated:YES]; }]; } 

Ok, para responder mi propia pregunta:

Como se mencionó anteriormente, lo mejor que se puede hacer es usar la API de Google Maps, es compatible con muchos formatos, pero por varias razones elegí ir con JSON.

Estos son los pasos para realizar una consulta JSON a Google Maps y obtener la coordenada de la consulta. Tenga en cuenta que no todas las validaciones correctas están hechas, esto es solo una Prueba de concepto.

1) Descargue un framework / biblioteca JSON para el iPhone, hay varios, elegí ir con este , es muy bueno y parece un proyecto activo, además de que varias aplicaciones comerciales parecen estar usándolo. Así que agrégalo a tu proyecto (instrucciones aquí ).

2) Para consultar una dirección en Google Maps, necesitamos construir una URL de solicitud como esta: http://maps.google.com/maps/geo?q=Paris+France

Esta url, devolverá un objeto JSON para la consulta “Paris + France”.

3) Código:

 //Method to handle the UISearchBar "Search", - (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar { //Perform the JSON query. [self searchCoordinatesForAddress:[searchBar text]]; //Hide the keyboard. [searchBar resignFirstResponder]; } 

Después de gestionar la búsqueda de UISearchBar, debemos realizar la solicitud a Google Maps:

 - (void) searchCoordinatesForAddress:(NSString *)inAddress { //Build the string to Query Google Maps. NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress]; //Replace Spaces with a '+' character. [urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]]; //Create NSURL string from a formate URL string. NSURL *url = [NSURL URLWithString:urlString]; //Setup and start an async download. //Note that we should test for reachability!. NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [connection release]; [request release]; } 

Por supuesto, debemos manejar la respuesta del servidor de GoogleMaps (Nota: faltan muchas validaciones)

 //It's called when the results of [[NSURLConnection alloc] initWithRequest:request delegate:self] come back. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //The string received from google's servers NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //JSON Framework magic to obtain a dictionary from the jsonString. NSDictionary *results = [jsonString JSONValue]; //Now we need to obtain our coordinates NSArray *placemark = [results objectForKey:@"Placemark"]; NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:@"Point.coordinates"]; //I put my coordinates in my array. double longitude = [[coordinates objectAtIndex:0] doubleValue]; double latitude = [[coordinates objectAtIndex:1] doubleValue]; //Debug. //NSLog(@"Latitude - Longitude: %f %f", latitude, longitude); //I zoom my map to the area in question. [self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude]; [jsonString release]; } 

Finalmente, la función de ampliar mi mapa, que ahora debería ser algo trivial.

 - (void) zoomMapAndCenterAtLatitude:(double) latitude andLongitude:(double) longitude { MKCoordinateRegion region; region.center.latitude = latitude; region.center.longitude = longitude; //Set Zoom level using Span MKCoordinateSpan span; span.latitudeDelta = .005; span.longitudeDelta = .005; region.span = span; //Move the map and zoom [mapView setRegion:region animated:YES]; } 

Espero que esto ayude a alguien porque la parte de JSON fue un verdadero dolor de entender, la biblioteca no está muy bien documentada en mi opinión, aún así es muy buena.

EDITAR:

Se modificó el nombre de un método para “searchCoordinatesForAddress:” debido a la pregunta @Leo. Debo decir que este método es bueno como una prueba de concepto, pero si planea descargar grandes archivos JSON, tendrá que adjuntar a un objeto NSMutableData para mantener toda la consulta en el servidor de google. (recuerde que las consultas HTTP vienen por piezas).

Este enlace lo ayuda si busca una región.

 NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress]; 

Si quieres buscar en una calle, este es el enlace corect

 NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=json",inAddress]; 

Tenga en cuenta que el segundo ? debe ser & .

Si alguien más está teniendo el mismo problema, aquí está el enlace: https://github.com/stig/json-framework/ desplácese hacia abajo a Project renombrado a SBJson

Además, aquí está el código para obtener todos los datos antes de que su aplicación lo use. Tenga en cuenta que el método de delegado ‘recibió datos’ ya que agrega el objeto de datos mutable con los datos descargados.

SIMPLEMENTE HE UTILIZADO MR GANDOS searchCoodinatesMETHOD COMO ES YA FUNCIONA BIEN

 - (void) searchCoordinatesForAddress:(NSString *)inAddress { //Build the string to Query Google Maps. NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false",inAddress]; //Replace Spaces with a '+' character. [urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]]; //Create NSURL string from a formate URL string. NSURL *url = [NSURL URLWithString:urlString]; //Setup and start an async download. //Note that we should test for reachability!. NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [connection release]; [request release]; } 

// PASO UNO // ESTO ES IMPORTANTE YA QUE CREA EL OBJETO DE DATOS MUTABLE TAN PRONTO COMO SE RECIBA UNA RESPUESTA

 -(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response { if (receivedGeoData) { [receivedGeoData release]; receivedGeoData = nil; receivedGeoData = [[NSMutableData alloc] init]; } else { receivedGeoData = [[NSMutableData alloc] init]; } } 

/// PASO DOS // ESTO ES IMPORTANTE YA QUE APLICA EL OBJETO DE DATOS CON LOS DATOS

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [receivedGeoData appendData:data]; } 

// PASO TRES …… // AHORA QUE TIENES TODOS LOS DATOS HAGA USO DE ÉL

 - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *jsonResult = [[NSString alloc] initWithData:receivedGeoData encoding:NSUTF8StringEncoding]; NSError *theError = NULL; dictionary = [NSMutableDictionary dictionaryWithJSONString:jsonResult error:&theError]; NSLog(@"%@",dictionary); int numberOfSites = [[dictionary objectForKey:@"results"] count]; NSLog(@"count is %d ",numberOfSites); } -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { // Handle the error properly } 

Puede usar el servicio API de Google para obtener latitud / longitud de una cadena de búsqueda textual. Asegúrese de pasar la ubicación actual del usuario para que los resultados sean relevantes. Lea las respuestas a esta pregunta: busque y muestre ubicaciones comerciales en MKMapView

Versión Swift, adaptada para iOS 9:

 let geocoder = CLGeocoder() geocoder.geocodeAddressString(addressString) { (placemarks, error) in if let center = (placemarks?.first?.region as? CLCircularRegion)?.center { let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.02, 0.02)) self.mapView.setRegion(region, animated: true) } } 

basado en la respuesta del usuario1466453.