42

我有一个应用程序需要具有类似的搜索功能,例如 Apple“地图”应用程序(包括在 iPhone、iPod Touch 和 iPad 中)。

有问题的功能应该不是一件难事,但我真的不知道如何在搜索栏中输入街道地址,然后获取该地址的坐标或可以帮助我实际移动地图的东西中心在那个地方。

我的意思是,我要查询什么,Apple 是否提供了“地址搜索 API 方法”?还是我需要直接使用谷歌地图 API?

我很想听听应该怎么做。

4

6 回答 6

56

这可能是最简单的方法。它使用苹果服务器进行地理编码。有时苹果服务器提供比谷歌更好的响应。很快(在 IOS 6.1 中)谷歌地图将完全脱离 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];
    }];
}
于 2012-06-19T12:47:03.757 回答
39

好的,回答我自己的问题:

如前所述,最好的办法是使用 Google Maps API,它支持很多格式,但出于几个原因,我选择使用 JSON。

因此,这里是对 Google Maps 执行 JSON 查询并获取查询坐标的步骤。请注意,并非所有正确的验证都已完成,这只是一个概念证明。

1)为iPhone下载一个JSON框架/库,有几个,我选择了这个,非常好,似乎是一个活跃的项目,加上几个商业应用程序似乎正在使用它。因此,将其添加到您的项目中(此处的说明)。

2) 要在 Google 地图中查询地址,我们需要构建一个请求 URL,如下所示: http ://maps.google.com/maps/geo?q=Paris+France

此 url 将为查询“Paris+France”返回一个 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 查询是分段进行的。)

于 2010-02-18T22:09:10.760 回答
2

如果其他人有同样的问题,这里的链接: https://github.com/stig/json-framework/ 向下滚动到项目重命名为 SBJson

此外,这里是在您的应用程序使用之前获取所有数据的代码。请注意,委托方法“确实收到了数据”,因为它将可变数据对象附加到下载的数据中。

我刚刚使用了 甘多斯先生 searchCoodinatesMETHOD AS IS AS IT WORKS WELL

- (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
}
于 2011-06-23T09:41:46.157 回答
2

如果您搜索区域,此链接会为您提供帮助。

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

请注意,第二个?应该是&.

于 2011-07-29T07:48:27.317 回答
2

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

基于user1466453的回答。

于 2016-02-16T18:47:20.477 回答
1

您可以使用 Google 的 API 服务从文本搜索字符串中获取纬度/经度坐标。请务必传递用户的当前位置,以便结果相关。阅读此问题的答案:Search and display business locations on MKMapView

于 2010-02-17T15:51:25.373 回答