Подтвердить что ты не робот

Как искать MKMapView с помощью UISearchBar?

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

2) Чтобы запросить Карты Google для адреса, нам нужно создать 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:

- (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 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 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 была настоящей болью, чтобы понять, что библиотека не очень хорошо документирована, по-моему, это очень хорошо.

ИЗМЕНИТЬ:

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

Ответ 2

Это, возможно, самый простой способ. Он использует серверы 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];
    }];
}

Ответ 3

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

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

Я ТОЛЬКО использовал MR GANDOS searchCoodinatesMETHOD КАК ЭТО РАБОТАЕТ ЭТО РАБОТАЕТ

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

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

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

}

///STEP TWO // ЭТО ОДИН ВАЖНО, КАК ЭТО ПРИНЯТЬ ОБЪЕКТ ДАННЫХ С ДАННЫМИ

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

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

Быстрая версия, адаптированная для 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.