I have a geocoder method and I want it to return the CLLocationCoordinate2D that it generates for me.
- (CLLocationCoordinate2D)geocode{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(0,0);
[geocoder geocodeAddressDictionary:self.placeDictionary completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count]) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
coordinate = location.coordinate;
} else {
NSLog(@"error");
}
}];
return coordinate;
}
The line coordinate = location.coordinate
produces an error however. XCode says coordinate
is an unassignable variable. Anyone see what I'm doing wrong?
update:
After following sebastian's advice, I got the code to compile, however, coordinate
is not being properly set. If you take a look at both of the NSLog statements i put in the method, the first one prints out the correct coordinates that I need assigned to coordinate
, however as soon as the if statement exits, coordinate
goes back to being set to (0,0). The second NSLog statement prints (0,0). Anyone know how I can fix this?
- (CLLocationCoordinate2D)geocode{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
__block CLLocationCoordinate2D geocodedCoordinate = CLLocationCoordinate2DMake(0,0);
[geocoder geocodeAddressDictionary:self.placeDictionary completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count]) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
geocodedCoordinate = location.coordinate;
NSLog(@"%f, %f", coordinate.longitude, coordinate.latitude);
} else {
NSLog(@"error");
}
}];
NSLog(@"%f, %f", coordinate.longitude, coordinate.latitude);
return coordinate;
}
You have to use the
__block
keyword if you want to assign to a variable that was defined outside the block's scope:Have a look at the Blocks and Variables section of Apple's Block Programming Topics
About the variable not getting set when it compiles:
geocodeAddressDictionary:completionHandler:
runs asynchronously. That means it returns immediately but the block gets executed later, when the results are available. You need to change the way you call your methods. At the moment you are probably doing something like thisWhat you have to do is more like this:
Running
[self geocode]
returns immediately andmyCoordinate
will be set when the block runs.If you are doing it that way, note that this could lead to a reference cycle, because self is being retained by the block.