ios 如何使用 UISearchBar 搜索 MKMapView?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2281798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to search MKMapView with UISearchBar?
提问by Goles
I have an application that needs to have a similar search feature like the Apple "Maps" application (included with iPhone, iPod Touch and iPad).
我有一个应用程序需要具有类似的搜索功能,例如 Apple“地图”应用程序(包含在 iPhone、iPod Touch 和 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 ?
我的意思是,我必须查询什么,Apple 是否提供“地址搜索 API 方法”?还是我需要直接使用谷歌地图 API?
I would love to hear how should it be done.
我很想听听它应该怎么做。
采纳答案by Goles
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.
如前所述,最好的做法是使用 Google Maps API,它支持多种格式,但出于多种原因,我选择使用 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.
所以这里是对谷歌地图执行 JSON 查询并获取查询坐标的步骤。请注意,并非所有正确的验证都已完成,这只是概念证明。
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).
1) 为iPhone下载一个JSON框架/库,有几个,我选择了这个,它非常好,似乎是一个活跃的项目,加上几个商业应用程序似乎在使用它。因此,将其添加到您的项目中(此处的说明)。
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
2) 要在 Google 地图中查询地址,我们需要构建这样的请求 URL:http: //maps.google.com/maps/geo?q=Paris+France
This url, will return a JSON object for the query "Paris+France".
此 url 将返回查询“Paris+France”的 JSON 对象。
3) Code:
3) 代码:
//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:
在我们处理完 UISearchBar 搜索之后,我们必须向谷歌地图发出请求:
- (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)
我们当然必须然后处理 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];
}
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.
希望这对某人有所帮助,因为 JSON 部分很难弄清楚,在我看来,该库的文档记录不是很好,但它仍然非常好。
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 . )
由于@Leo 问题,将一种方法名称修改为“searchCoordinatesForAddress:”。我不得不说,这种方法作为概念证明很好,但是如果您打算下载大型 JSON 文件,则必须附加到 NSMutableData 对象以将所有查询保存到谷歌服务器。(请记住,HTTP 查询是分段进行的。)
回答by Shakir Zareen
This maybe the easiest method. It uses apple servers for geocoding. Sometimes the apple servers provide better response than google. And soon (in IOS 6.1) the google maps will be completely out of IOS. So it is good if the app stays inside the apples provided features.
这可能是最简单的方法。它使用苹果服务器进行地理编码。有时苹果服务器提供比谷歌更好的响应。很快(在 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];
}];
}
回答by timv
If anyone else is having the same issue, heres the link: https://github.com/stig/json-framework/scroll down to Project renamed to SBJson
如果其他人有同样的问题,这里是链接:https: //github.com/stig/json-framework/向下滚动到更名为 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
我刚刚使用了 GANDOS 先生搜索坐标方法,因为它运行良好
- (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
}
回答by Vali
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];
Noticethat the 2nd ?
should be &
.
请注意,第二个?
应该是&
。
回答by Eric
Swift version, adapted for iOS 9:
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)
}
}
based on user1466453's answer.
基于 user1466453 的回答。
回答by William Denniss
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
您可以使用 Google 的 API 服务从文本搜索字符串中获取经纬度坐标。确保传递用户的当前位置,以便结果相关。阅读此问题的答案:在 MKMapView 上搜索和显示营业地点