Objective-C - 根据用户输入的查询查找街道

8
我希望允许用户搜索街道名称,并在UITableView中显示结果。目前地区不重要,可以来自任何地区。
我在搜索中找不到任何相关的示例,也不知道应该使用CLLocation还是MKLocalSearch。
根据文档,我应该使用MKLocalSearch:
虽然本地搜索和地理编码类似,但它们支持不同的用例。当您想在地图坐标和结构化地址(例如通讯录地址)之间进行转换时,请使用地理编码。当您想查找与用户输入匹配的一组位置时,请使用本地搜索。
但是,我已经尝试了两种方法,它只给我返回1个结果(即使有一个NSArray返回)。
这是CLGeocoder方法的实现:
CLGeocoder *geocoding = [[CLGeocoder alloc] init];
[geocoding geocodeAddressString:theTextField.text completionHandler:^(NSArray *placemarks, NSError *error) {
    if (error) {
        NSLog(@"%@", error);
    } else {
        NSLog(@"%i", [placemarks count]);
        for(CLPlacemark *myStr in placemarks) {
            NSLog(@"%@", myStr);
    }
    }
}];

以下是我尝试使用MKLocalSearch的代码:

MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = theTextField.text;
request.region = self.region;

localSearch = [[MKLocalSearch alloc] initWithRequest:request];

[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){

    if (error != nil) {
        [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Map Error",nil)
                                    message:[error localizedDescription]
                                   delegate:nil
                          cancelButtonTitle:NSLocalizedString(@"OK",nil) otherButtonTitles:nil] show];
        return;
    }

    if ([response.mapItems count] == 0) {
        [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"No Results",nil)
                                    message:nil
                                   delegate:nil
                          cancelButtonTitle:NSLocalizedString(@"OK",nil) otherButtonTitles:nil] show];
        return;
    }
    self.streets = response;
    [self.streetsTableView reloadData];
}];

MKLocalSearch似乎在某些情况下返回多个响应,但这些与地点搜索而非街道名称搜索有关。

提前感谢。


你试过将区域设置为nil吗?或者你能分享一下关于self.region的更多细节吗? - Mert Buran
我有一个MapView,我正在使用MapView.region作为self.region。 - CristiC
根据我的经验,MKLocalSearch非常原始。您是否因任何原因反对使用Google Places API? - lead_the_zeppelin
谷歌有一个更有用的API(https://developers.google.com/maps/documentation/geocoding/),MKLocalSearch仅适用于简单任务。 - Sega-Zero
3个回答

4
这是我能找到的最接近的方法。这涉及使用谷歌地点API Web服务

注意:您可能可以使用其Google Maps API等。我相信还有其他方式从各种Google API获取此信息。
 NSURL *googlePlacesURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%@&location=%f,%f&sensor=true&key=API_KEY", formattedSearchText, location.coordinate.latitude,
                                                   location.coordinate.longitude]];

响应是一个 JSON 对象。将其转换为字典。
 NSDictionary *response = [NSJSONSerialization JSONObjectWithData:_googlePlacesResponse
                                                                    options:NSJSONReadingMutableContainers error:&error];

if([[response objectForKey:@"status"] isEqualToString:@"OK"])
{
    NSArray *predictions = [response objectForKey:@"predictions"];
    for(NSDictionary *prediction in predictions)
    {
        NSArray *addressTypes = [prediction objectForKey:@"types"];
        if([addressTypes containsObject:@"route"])
        {
            //This search result contains a street name. 
            //Now get the street name.
            NSArray *terms = [prediction objectForKey:@"terms"];
            NSDictionary *streetNameKeyValuePair = [terms objectAtIndex:0];
            NSLog(@"%@",[streetNameKeyValuePair objectForKey@"value"]);
        }
    }
}

可能的“类型”似乎是:
  • 路线 -> 街道名称
  • 本地性 -> 城市/位置名称
  • 政治 -> 州等
  • 地理编码 -> 经度/纬度可用
  • 您可以使用那些仅包含“路线”作为地址类型的“预测”来填充表视图。这可能有效。

    1
    是的,没错。在看到你的回答之前,我也做了同样的事情 :)。这个链接对我很有帮助:https://dev59.com/wIHba4cB1Zd3GeqPYv9Z#25318167 - CristiC

    2

    CLGeocoder可以简单地返回地址格式。将其添加到您的代码中并与mapitems内容一起使用。

    MKLocalSearchRequest *request = [MKLocalSearchRequest new];
    request.naturalLanguageQuery = @"Pizza";
    request.region = MKCoordinateRegionMake(location.coordinate, MKCoordinateSpanMake(.01, .01));
    MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
    [search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
        NSArray *mapItems = response.mapItems;
        for (MKMapItem *mapItem in mapItems) {
            MKPointAnnotation *point = [MKPointAnnotation new];
            point.coordinate = mapItem.placemark.coordinate;`
        }
    }];
    

    1
    返回的数组包含mapItems,您可以遍历该数组以提取所有的mapItems,如下所示:
    myMatchingItems = [[NSMutableArray alloc] init];
    for (MKMapItem *item in response.mapItems){
                        [myMatchingItems addObject:item];
        }
    

    每个mapItem.placemark.thoroughfare包含所找到的位置的街道信息。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接