Reputation: 3042
I am trying to store a String Value inside the completion handler but its scope is restricted to that block only. How to resolve it ?
// Do any additional setup after loading the view, typically from a nib.
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
NSString *co;
[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");
if (error){
NSLog(@"Geocode failed with error: %@", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"placemark.country %@",placemark.country);
co = placemark.country;
//
}];
NSLog(@"%@",co);
At this line the value of co becomes null again. Please let me know, how can retain the value outside the completion handler, which I store inside completion handler.
Upvotes: 2
Views: 1391
Reputation: 4446
The issue isn't a matter of scope, it's that the log is called before the completion block. The reverse geocode call is asynchronous. It will return the block whenever it's done with what it's doing, but in the meantime, the rest of your method will execute. If you print co the line after you set its value but within the completion block, it will display the correct value.
Example:
[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");
if (error){
NSLog(@"Geocode failed with error: %@", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"placemark.country %@",placemark.country);
co = placemark.country;
// The completion block has returned and co has been set. The value equals placemark.country
NSLog(@"%@",co);
}];
// This log is executed before the completion handler. co has not yet been set, the value is nil
NSLog(@"%@",co);
If you need to use the co variable outside of the block, you should call the methods it will be used in from within the completion block:
[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
[self myMethodWithCountry:placemark.country];
}];
- (void)myMethodWithCountry:(NSString *)country {
// country == placemark.country
}
Upvotes: 4
Reputation: 5091
As Julie suggested, add __block
before NSString *co;
i.e. __block NSString *co;
. That's two underscores btw.
Upvotes: -1
Reputation: 3506
The NSLog
command you wrote will work before you complete the block. Since this happens you will get null
. One thing you can do is print the value of co
inside the block instead of doing it outside.
OR
change the declaration of co
as follows:
__block NSString *co= nil;
Upvotes: 2