9

我想恢复这个这个问题,因为这个问题对我来说仍然存在,所以我正在写一个新问题。

这是我的代码:

- (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 只返回一个地标,日志打印出一个不错的

“地标[计数] = 1”。

我的问题是,有谁知道是否有另一种方法来检索前向地理编码或其他一些神奇的东西(Apple 地图应用程序为我执行的同一查询显示多个标记,例如“通过 roma”)?


编辑 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);
    }];

...我得到通常的“地标 [count] = 1”

4

2 回答 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];
    }
}];

我想这一切都取决于您期望收到什么样的多次点击。

于 2013-04-03T19:50:48.637 回答
0

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

很难找到这样的例子,当然它们将来可能会改变。出于某种原因,Apple 地图应用程序显示“您的意思是...”对话框以获取更多地址。

于 2013-04-11T07:11:16.547 回答