CLGeocoder曾经返回一个地标

时间:2013-04-03 16:40:37

标签: ios clgeocoder

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

这是我的代码:

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

我使用此解决方案是因为Google条款会阻止使用Google地图API而不会在Google地图上显示结果。

问题与前面提到的问题相同:CLGeocoder只返回一个地标,日志打印出一个不错的

  

“placemarks [count] = 1”。

我的问题是,是否有人知道是否有其他方法可以检索前向地理编码或其他一些神奇的东西(Apple地图应用程序为我所做的同一查询显示多个标记,例如“通过roma”)?< / p>


编辑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,代码来自here

    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”

2 个答案:

答案 0 :(得分: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];
    }
}];

我想这一切都取决于你期望收到多少次点击。

答案 1 :(得分:0)

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

找到这样的例子非常困难,当然,未来可能会有所改变。出于某种原因,Apple地图应用程序会显示更多地址的“您是不是......”对话框。