简体   繁体   English

在地图视图中使用CLGeocoder而不是私有API

[英]Using CLGeocoder instead of private API in map view

I was using google API to obtain the geo co-ordinates. 我正在使用google API获取地理位置坐标。 The code I have been using till now is as below 到目前为止,我一直在使用的代码如下

-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr {

NSString *urlStr = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv",
                    [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *locationStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlStr] encoding:NSStringEncodingConversionAllowLossy error:nil];
NSArray *items = [locationStr componentsSeparatedByString:@","];
double latitude = 0.0;
double longitude = 0.0;

//NSLog(@"items array %@", items);

if([items count] >= 4 && [[items objectAtIndex:0] isEqualToString:@"200"]) {
    latitude = [[items objectAtIndex:2] doubleValue];
    longitude = [[items objectAtIndex:3] doubleValue];
}
else {
    //NSLog(@"Address, %@ not found: Error %@",addressStr, [items objectAtIndex:0]);
}

CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude;
return location;
}

I wish to use CLGeocoder in the place of google API to obtain the location co-ordinates from an address string. 我希望使用CLGeocoder代替Google API从地址字符串中获取位置坐标。

I have been working with CLGeocoder seen from examples online. 我一直在与CLGeocoder合作,从在线示例中可以看到。 I find it a bit hard task working with the CLGeocoder . 我发现使用CLGeocoder有点困难。 I tried to use the CLGeocoder without changing much from my previous code, so that I don't have to make big changes in the existing code. 我尝试使用CLGeocoder而不对以前的代码进行太多更改,因此不必在现有代码中进行重大更改。

CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:addressStr completionHandler:^(NSArray *placemarks, NSError *error) {
    self.placemarksArray = placemarks;
    CLPlacemark *placeInfo = [placemarks objectAtIndex:0];
    NSString *latitudeString = [NSString stringWithFormat:@"%f",placeInfo.location.coordinate.latitude ];
    NSString *longitudeString = [NSString stringWithFormat:@"%f",placeInfo.location.coordinate.longitude ];
    NSLog(@"latitudeString %@", latitudeString);
    NSLog(@"longitudeString %@", longitudeString);

    _latitudes = placeInfo.location.coordinate.latitude;
    _longitudes = placeInfo.location.coordinate.longitude;
}];
location.latitude = _latitudes;
location.longitude = _longitudes;
return location;

But what happens is that, the map view gets loaded before the block is executed. 但是发生的是,在执行该块之前加载了地图视图。 The exact value of the location is not returned in this case. 在这种情况下,不会返回位置的确切值。

My question is : 我的问题是:

  1. Is it possible to use CLGeocoder , without making much changes to my previous code. 是否可以使用CLGeocoder ,而无需对我之前的代码进行太多更改。 Or should I need to change the whole structure. 还是我需要更改整个结构。
  2. From the 2nd block of code I have tried, what I am I doing wrong and how may I correct it? 从我尝试过的第二段代码中,我在做错什么,我该如何纠正?

Edit: The above method is called from viewDidLoad 编辑:从viewDidLoad调用上述方法

CLLocationCoordinate2D mapCenter = [self getLocationFromAddressString:fullAddress];
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
            [annotationPoint setCoordinate:mapCenter];
            [annotationPointsArray addObject:annotationPoint];
addAnnotation = [[[MyAddressAnnotation alloc] initWithCoordinate:mapCenter title:firstName SubTitle:lastName]autorelease];

 [mapView addAnnotation:addAnnotation];

This gets executed after getting the CLLocationCoordinate2D latitude and longitude values from getGeoLocation method. 从getGeoLocation方法获取CLLocationCoordinate2D纬度和经度值后,将执行此操作。

CLGeocoder happens asynchronously (the fact that it's done in a block gives that away), and thus _latitudes and _longitudes are not set by the time the method, itself, returns. CLGeocoder异步发生(事实是在一个块中完成了这一事实),因此_latitudes_longitudes不会在方法本身返回时设置。 So, likely, yes, some slight restructuring of your code will be needed. 因此,很可能,是的,将需要对代码进行一些轻微的重组。 It's hard for us to advise as we don't see the code that calls this routine. 我们很难建议,因为我们看不到调用此例程的代码。 Bottom line, you have to refactor that code so that rather than returning the location , you have the completionHandler of geocodeAddressString invoke whatever you need done. 底线是,你必须重构的代码,这样,而不是返回的location ,你有completionHandlergeocodeAddressString调用任何你需要完成。

Looking at your revised code, it appears that your viewDidLoad is taking the location coordinates and creating an annotation. 查看修改后的代码,看来viewDidLoad正在获取位置坐标并创建注释。 Just do that adding of the annotation inside the geocoded block. 只需在地理编码块添加注释即可。

Thus: 从而:

-(CLLocationCoordinate2D) geocodeAddressString:(NSString*)addressStr title:(NSString *)title subtitle:(NSString *)subtitle
{
    CLGeocoder *geocoder = [[[CLGeocoder alloc] init] autorelease];
    [geocoder geocodeAddressString:addressStr completionHandler:^(NSArray *placemarks, NSError *error) {
        self.placemarksArray = placemarks;
        CLPlacemark *placeInfo = [placemarks objectAtIndex:0];

        id<MKAnnotation> annotation = [[[MyAddressAnnotation alloc] initWithCoordinate:placeInfo.location.coordinate 
                                                                                 title:title
                                                                              SubTitle:subtitle] autorelease];

        [self.mapView addAnnotation:addAnnotation];
    }];
}

And then, viewDidLoad would call it as follows: 然后, viewDidLoad将按如下方式调用它:

[self geocodeAddressString:fullAddress title:firstName subtitle:lastName]; 

Nothing of magic, but you have to poke your mapview, inside your block: 没什么神奇的,但是您必须在块内戳地图视图:

self.mapView.centerCoordinate = placeInfo.location.coordinate //or equivalent of this, like latitudes and longitudes change

If you want to avoid the mapview being drawn twice, you need to intercept events of MKMapview (especially mapViewWillStartLoadingMap ), implement them within your code, and put proper flags to avoid the map being drawn till the time reverse geocoding block hasn't been executed. 如果要避免两次绘制mapview,则需要拦截MKMapview的事件(尤其是mapViewWillStartLoadingMap ),在代码中实现它们,并放置适当的标志来避免在未执行时间反向地理编码块之前绘制地图。

Try this answer. 试试这个答案。

Call method with some part of delay (ie 2 seconds). 延迟部分(即2秒)的调用方法。

[self performSelector:@selector(geoCodeUsingAddress:) withObject:userAddress afterDelay:2.0];

Calling GetCurrentLocation function 调用GetCurrentLocation函数

- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)addressStr
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:addressStr completionHandler:^(NSArray *placemarks, NSError *error) {
       self.placemarksArray = placemarks;
       CLPlacemark *placeInfo = [placemarks objectAtIndex:0];

       NSString *latitudeString = [NSString stringWithFormat:@"%f",placeInfo.location.coordinate.latitude ];
       NSString *longitudeString = [NSString stringWithFormat:@"%f",placeInfo.location.coordinate.longitude ];

       NSLog(@"latitudeString %@", latitudeString);
       NSLog(@"longitudeString %@", longitudeString);

       _latitudes = placeInfo.location.coordinate.latitude;
       _longitudes = placeInfo.location.coordinate.longitude;
    }];

    location.latitude = _latitudes;
    location.longitude = _longitudes;

    return location;
}

Hopefully, it will help you. 希望会对您有所帮助。

Thanks. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM