Как искать MKMapView с UISearchBar? - PullRequest
       35

Как искать MKMapView с UISearchBar?

42 голосов
/ 17 февраля 2010

У меня есть приложение, которое должно иметь функцию поиска, аналогичную приложению «Карты» Apple (входит в комплект поставки iPhone, iPod Touch и iPad).

Рассматриваемая функция не должна быть сложной, но я действительно не знаю, как ввести уличный адрес в строку поиска, а затем получить координаты для этого адреса или что-то, что может помочь мне на самом деле переместиться карта и центр в этом месте.

Я имею в виду, что я должен запросить, предоставляет ли Apple «метод поиска адреса API»? или мне нужно напрямую использовать API карт Google?

Мне бы очень хотелось услышать, как это сделать.

Ответы [ 6 ]

56 голосов
/ 19 июня 2012

Это, пожалуй, самый простой метод. Он использует серверы Apple для геокодирования. Иногда серверы Apple обеспечивают лучший отклик, чем Google. И скоро (в IOS 6.1) карты Google будут полностью вне IOS. Так что хорошо, если приложение остается внутри функций, предоставляемых яблоками.

-(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];
    }];
}
39 голосов
/ 19 февраля 2010

Хорошо, чтобы ответить на мой собственный вопрос:

Как уже упоминалось ранее, лучше всего использовать API Карт Google, он поддерживает множество форматов, но по нескольким причинам я решил использовать JSON.

Итак, вот шаги, чтобы выполнить JSON-запрос к Google Maps и получить координату запроса. Обратите внимание, что не все правильные проверки сделаны, это только подтверждение концепции.

1) Скачайте фреймворк / библиотеку JSON для iPhone, их несколько, я выбрал этот , он очень хороший и кажется активным проектом, плюс несколько коммерческих приложений, кажется, используют Это. Поэтому добавьте его в свой проект (инструкции здесь ).

2) Чтобы запросить у Google Maps адрес, нам нужно создать URL-адрес запроса: http://maps.google.com/maps/geo?q=Paris+France

Этот URL вернет объект JSON для запроса "Париж + Франция".

3) Код:

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

    //Hide the keyboard.
    [searchBar resignFirstResponder];
}

После того как мы обработаем поиск UISearchBar, мы должны сделать запрос к 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];
}

Затем мы должны обработать ответ сервера GoogleMaps (Примечание: пропущено много проверок)

//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];
}

Наконец, функция увеличения моей карты, которая теперь должна быть тривиальной.

- (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];
}

Надеюсь, это кому-нибудь поможет, потому что JSON-часть была очень трудной для понимания, библиотека, на мой взгляд, не очень хорошо документирована, но все же она очень хорошая.

РЕДАКТИРОВАТЬ:

Из-за вопроса @Leo одно имя метода изменено на "searchCoordinatesForAddress:". Я должен сказать, что этот метод является хорошим доказательством концепции, но если вы планируете загружать большие файлы JSON, вам нужно будет добавить объект NSMutableData, чтобы сохранить весь запрос на сервере Google. (помните, что HTTP-запросы приходят по частям.)

2 голосов
/ 16 февраля 2016

Swift версия, адаптированная для 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)
    }
}

основано на ответе пользователя 1466453.

2 голосов
/ 29 июля 2011

Эта ссылка поможет вам при поиске в регионе.

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

Если вы хотите найти улицу, это основная ссылка

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

Обратите внимание , что 2-й ? должен быть &.

2 голосов
/ 23 июня 2011

Если у кого-то еще есть такая же проблема, вот ссылка: https://github.com/stig/json-framework/ прокрутите вниз до Проект переименован в SBJson

Кроме того, вот код для получения всех данных, прежде чем ваше приложение будет их использовать. Обратите внимание, что метод делегата «действительно получил данные», так как он добавляет изменяемый объект данных к загруженным данным.

Я ПРОСТО ИСПОЛЬЗУЛ MR GANDOS searchCoodinates МЕТОД КАК ЭТО, КАК ЭТО РАБОТАЕТ ХОРОШО

- (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];
}

// ШАГ ПЕРВЫЙ // ЭТО ОДНО ВАЖНО, КАК ЭТО СОЗДАЕТ ОБЪЕКТ МУТАБИЛЬНЫХ ДАННЫХ, КАК СКОРО, КАК ПОЛУЧИТ ОТВЕТ

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

}

/// ШАГ ВТОРОЙ // ЭТО ОДНО ВАЖНО, КАК ЭТО ДОБАВЛЯЕТ ОБЪЕКТ ДАННЫХ С ДАННЫМИ

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

// ШАГ ТРЕТИЙ ...... // СЕЙЧАС ВЫ ИСПОЛЬЗУЕТЕ ВСЕ ДАННЫЕ

- (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
}
1 голос
/ 17 февраля 2010

Вы можете использовать сервис API Google, чтобы получить координаты широты / долготы из строки текстового поиска. Обязательно передайте текущее местоположение пользователя, чтобы результаты были релевантными. Прочитайте ответы на этот вопрос: Поиск и отображение местоположения предприятия в MKMapView

...