I was using google API to obtain the geo co-ordinates. 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.
I have been working with CLGeocoder
seen from examples online. I find it a bit hard task working with the 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 *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 :
CLGeocoder
, without making much changes to my previous code. Or should I need to change the whole structure.Edit: The above method is called from 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.
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. 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.
Looking at your revised code, it appears that your viewDidLoad
is taking the location coordinates and creating an annotation. 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:
[self geocodeAddressString:fullAddress title:firstName subtitle:lastName];