如何使用UISearchBar搜索MKMapView?

发布于 2024-08-22 02:18:24 字数 232 浏览 3 评论 0原文

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

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

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

我很想听听应该如何完成。

I have an application that needs to have a similar search feature like the Apple "Maps" application (included with iPhone, iPod Touch and iPad).

The feature in question should not be a hard thing to do, but I'm really clueless about how to input a Street Address in the search bar, and then obtaining coordinates for that address or something that can help me to actually move the map and center in that place.

I mean, what do I have to query, does Apple provide an "address searching API method" ? or I need to use the google maps API directly ?

I would love to hear how should it be done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

﹉夏雨初晴づ 2024-08-29 02:18:24

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

正如之前提到的,最好的办法是使用 Google Maps API,
它支持很多格式,但出于多种原因我选择使用 JSON。

以下是对 Google 地图执行 JSON 查询并获取查询坐标的步骤。请注意,并未完成所有正确的验证,这只是概念证明。

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

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

此网址将为查询“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问题,将一种方法名称修改为“searchCooperativesForAddress:”。我不得不说,这种方法作为概念证明很好,但如果您计划下载大 JSON 文件,则必须附加到 NSMutableData 对象以保存对 google 服务器的所有查询。 (请记住,HTTP 查询是分段进行的。)

Ok, to answer my own question:

As was mentioned before, the best thing to do is to use the Google Maps API,
it supports a lot of formats but for several reasons I chose to go with JSON.

So here are the steps to perform a JSON query to Google Maps and obtain the coordinate of the query. Note that not all the correct validations are done, this is only a Proof of concept.

1) Download a JSON framework/library for the iPhone, there are several, I chose to go with this one, it's very good and seems an active project, plus several comercial applications seem to be using it. So add it to your project ( instructions here ).

2) To query Google Maps for an address we need to build a request URL like this:
http://maps.google.com/maps/geo?q=Paris+France

This url, will return a JSON object for the query "Paris+France".

3) Code:

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

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

After we handle the UISearchBar search, we must make the request to 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];
}

We must of course then handle the response of the GoogleMaps server ( Note: a lot of validations missing)

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

Finally the function to zoom my map, which should by now be a trivial thing.

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

Hope this helps someone because the JSON part was a real pain to figure out, the library is not very well documented in my opinion, still it's very good.

EDIT:

Modified one method name to "searchCoordinatesForAddress:" because of @Leo question. I have to say that this method is good as a proof of concept but if you plan to download big JSON files , you will have to append to a NSMutableData object to hold all the query to the google server. ( remember that HTTP queries come by pieces . )

甜柠檬 2024-08-29 02:18:24

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

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

注意,第二个应该是&

This link helps you if you search a region.

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

If you want to search a street this is the corect link

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

Notice that the 2nd ? should be &.

暗喜 2024-08-29 02:18:24

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 的回答。

Swift version, adapted for 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)
    }
}

based on user1466453's answer.

入怼 2024-08-29 02:18:24

如果其他人也遇到同样的问题,请点击以下链接:
https://github.com/stig/json-framework/
向下滚动到项目重命名为 SBJson

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

我刚刚使用了甘多斯先生的 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];
}

// 第一步
// 这一步很重要,因为它会在收到响应后立即创建可变数据对象

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

If anyone else is having the same issue, heres the link:
https://github.com/stig/json-framework/
scroll down to Project renamed to SBJson

Also, here is the code for getting all the data before your app uses it. Note the delegate method 'did receive data' as it appends the mutable data object with the downloaded data.

I JUST USED MR GANDOS searchCoodinatesMETHOD AS IT 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];
}

// STEP ONE
// THIS ONE IS IMPORTANT AS IT CREATES THE MUTABLE DATA OBJECT AS SOON AS A RESPONSE IS RECEIVED

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

}

/// STEP TWO
// THIS ONE IS IMPORTANT AS IT APPENDS THE DATA OBJECT WITH THE DATA

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

// STEP THREE......
// NOW THAT YOU HAVE ALL THE DATA MAKE USE OF IT

- (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
}
紫﹏色ふ单纯 2024-08-29 02:18:24

您可以使用 Google 的 API 服务从文本搜索字符串获取纬度/经度坐标。请务必传递用户的当前位置,以便结果具有相关性。阅读此问题的答案:在 MKMapView 上搜索和显示营业地点

You can use Google's API service to get lat/long coords from a textual search string. Be sure to pass the user's current location so the results are relevant. Read the answers to this question: Search and display business locations on MKMapView

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文