CLGeocoder是否会返回一个地标?

10

我希望重新激活此问题此问题,因为这个问题对我来说仍然存在,所以我要写一个新的问题。

这是我的代码:

- (SVGeocoder*)initWithParameters:(NSMutableDictionary*)parameters completion:(SVGeocoderCompletionHandler)block {
self = [super init];

self.operationCompletionBlock = block;

Class cl = NSClassFromString(@"CLGeocoder");
if (cl != nil)
{
    if (self.geocoder_5_1 == nil) {
        self.geocoder_5_1 = [[cl alloc] init];
    }

    NSString *address = [parameters objectForKey:kGeocoderAddress];
    [self.geocoder_5_1 geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
        NSMutableArray *svplacemarks = [NSMutableArray arrayWithCapacity:1];
        SVPlacemark *placemark;
        NSLog(@"placemarks[count] = %i", [placemarks count]);
        for (CLPlacemark *mark in placemarks) {
            placemark = [[SVPlacemark alloc] initWithPlacemark:mark];
            [svplacemarks addObject:placemark];
        }

        self.operationCompletionBlock([NSArray arrayWithArray:svplacemarks],nil,error);
    }];

}
else
{
    self.operationRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://maps.googleapis.com/maps/api/geocode/json"]];
    [self.operationRequest setTimeoutInterval:kSVGeocoderTimeoutInterval];

    [parameters setValue:@"true" forKey:kGeocoderSensor];
    [parameters setValue:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] forKey:kGeocoderLanguage];
    [self addParametersToRequest:parameters];

    self.state = SVGeocoderStateReady;
}
return self;
}

这是我个人版本(相当粗糙)的SVGeocoder,它使用CLGeocoder进行正向地理编码,并对iOS<5.1进行了向后兼容处理。
我使用这种解决方案是因为谷歌条款禁止在不显示谷歌地图结果的情况下使用地图API。
问题与先前提到的问题相同:CLGeocoder仅返回一个地标,日志打印出漂亮的“placemarks [count] = 1”。
我的问题是,是否有其他检索正向地理编码的方法,或者其他神奇的事情(例如,苹果地图应用程序显示相同查询“通过罗马”的多个标记)?
编辑Rob的解决方案
Class mkLocalSearch = NSClassFromString(@"MKLocalSearch");

if (mkLocalSearch != nil)
{
    NSString *address = [parameters objectForKey:kGeocoderAddress];
    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];

    request.region = MKCoordinateRegionForMapRect(MKMapRectWorld);

    request.naturalLanguageQuery = address;

    MKLocalSearch *localsearch = [[MKLocalSearch alloc] initWithRequest:request];
    [localsearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {

        NSMutableArray *svplacemarks = [NSMutableArray arrayWithCapacity:1];
        SVPlacemark *placemark;
        NSLog(@"response.mapItems[count] = %i", [response.mapItems count]);

        for (MKMapItem *item in response.mapItems)
        {
            placemark = [[SVPlacemark alloc] initWithPlacemark:item.placemark];
            [svplacemarks addObject:placemark];
        }

        self.operationCompletionBlock([NSArray arrayWithArray:svplacemarks],nil,error);
    }];
}

这是一个有趣的解决方案,提供了另一个视角。不幸的是,即使我将区域设置为全球,我仍然得到了一个漂亮的日志。

response.mapItems[count] = 1

查询是“via roma”,这是意大利非常常见的街道名称,以至于我认为我们在任何意大利城市都可以找到它。
也许我做错了什么?
编辑2 - 新测试:
将World Rect转换为CLRegion,代码来自这里
    NSString *address = [parameters objectForKey:kGeocoderAddress];

    // make a conversion from MKMapRectWorld to a regular CLRegion
    MKMapRect mRect = MKMapRectWorld;
    MKMapPoint neMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), mRect.origin.y);
    MKMapPoint swMapPoint = MKMapPointMake(mRect.origin.x, MKMapRectGetMaxY(mRect));

    float ewDelta= neMapPoint.x - swMapPoint.x;
    float nsDelta= swMapPoint.y - neMapPoint.y;

    MKMapPoint cMapPoint = MKMapPointMake(ewDelta / 2 + swMapPoint.x, nsDelta / 2 + neMapPoint.y);

    CLLocationCoordinate2D neCoord = MKCoordinateForMapPoint(neMapPoint);
    CLLocationCoordinate2D swCoord = MKCoordinateForMapPoint(swMapPoint);

    CLLocationCoordinate2D centerCoord = MKCoordinateForMapPoint(cMapPoint);

    CLLocationDistance diameter = [self getDistanceFrom:neCoord to:swCoord];

// i don't have the map like showed in the example so i'm trying to center the search area to the hypothetical center of the world
    CLRegion *clRegion = [[CLRegion alloc] initCircularRegionWithCenter:centerCoord radius:(diameter/2) identifier:@"worldwide"];
    [self.geocoder_5_1 geocodeAddressString:address inRegion: clRegion completionHandler:^(NSArray *placemarks, NSError *error) {
        NSMutableArray *svplacemarks = [NSMutableArray arrayWithCapacity:1];
        SVPlacemark *placemark;
        NSLog(@"placemarks[count] = %i", [placemarks count]);
        for (CLPlacemark *mark in placemarks) {
            placemark = [[SVPlacemark alloc] initWithPlacemark:mark];
            [svplacemarks addObject:placemark];
        }

        self.operationCompletionBlock([NSArray arrayWithArray:svplacemarks],nil,error);
    }];

...然后我得到了通常的“placemark [count] = 1”

(这句话是关于it技术的)。
2个回答

5
显然,如果地址有多个匹配项(例如,区域足够大以致简单的街道地址不明确),CLGeocoder会返回多个地标,但通常情况下,如果区域足够小或提供的地址足够唯一,则它将找到一个匹配项。
虽然这不是通用解决方案,但自iOS 6.1以来,您可以使用MKLocalSearch进行更通用的查找(包括企业名称等)。
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.mapView.region;
request.naturalLanguageQuery = textField.text;

MKLocalSearch *localsearch = [[MKLocalSearch alloc] initWithRequest:request];
[localsearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
    for (MKMapItem *item in response.mapItems)
    {
        Annotation *annotation = [[Annotation alloc] initWithPlacemark:item.placemark];
        annotation.title = item.name;
        annotation.phone = item.phoneNumber;
        annotation.subtitle = item.placemark.addressDictionary[(NSString *)kABPersonAddressStreetKey];
        [self.mapView addAnnotation:annotation];
    }
}];

我想这完全取决于你期望接收到的多个点击类型。

感谢罗布的回答。该应用程序的目的类似于卫星导航器。我将编辑我的帖子以展示您的解决方案的实现。 - Alex75
2
无论使用哪种解决方案(无论是CLGeoCoder还是MKLocalSearch),我都只得到一个结果。我在德国的柏林,当搜索“San”时,我得到的是“圣地亚哥,加利福尼亚州”而不是“旧金山,加利福尼亚州”。我希望两者都能出现(地球上有很多“San…”)。 - Julian F. Weinert
@Julian - 我同意。这两个方法都不能返回详尽的列表。使用 CLGeocoder,我最多只能看到1或2个条目。它感觉像是一种“最佳猜测”方法,返回两三个条目。使用 MKLocalSearch,你会得到更多的结果(例如,在任何特定城市搜索“餐厅”,你会得到一个餐厅列表),但这并不是详尽的列表(稍微改变区域,你就可以得到非常不同的结果列表)。 - Rob
是的。经过更多的阅读、测试和印象,我相当确定它只搜索兴趣点,因为大城市总是有自己的“地址”,你会找到它们。地址查找肯定需要不同的东西,据我所知,他们没有内置任何东西... - Julian F. Weinert

0

有一些地址CLGeocoder确实会返回多个地标。我发现的一个例子是“以色列海法Herzel 13号”。我使用geocodeAddressDictionary:completionHandler:方法,对于该地址得到了相同的2个结果(可以将其设置为街道/城市/国家,也可以只将其设置为街道-结果相同)。

这样的例子很难找到,而且它们在未来可能会改变。由于某种原因,Apple Maps应用程序会对更多地址显示“您是否是要...”对话框。


1
是的...问题只是:“苹果是如何做到的?”直到今天我还没有找到答案。 - Alex75

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