Get Location name from reverseGeocodeLocation

1k views Asked by At

I want to find out photos location using reverseGeocodeLocation. I use the below function

@interface GalleryPhotosViewController ()
{
CLPlacemark *placemark;
}
@end

-(NSString *)getLocation:(CLLocation *)locations{
CLGeocoder *geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:locations completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
    placemark = [placemarks lastObject];
}];
return placemark.name;
}

I could not get that name when call the function but I get that after execution of other parts of code. I know that reverseGeocodeLocation has a completion block, it is handed off to another thread when execution reaches it. But I need to get that name when call the function. I go through many solutions but could not solve my problem. I want to receive location name in currentLocation.

CLLocation *loc = asset.location;
NSString *currentLocation = [self getLocation:loc];

Where should I change my code. Please help.

3

There are 3 answers

2
Gurdev Singh On

The method reverseGeocodeLocation of class CLGeocoder runs asynchronously hence you will not get the location data as a return value from the called function. It uses the completion handler where the location data is returned and you can use that completion handler block to update the UI or any further processing of your location data.

1
Darshan On

Get city,state and address you have to pass latitude and longitude, so pass latitude and longitude will pass to geocoder block and within block you will placemarks array.

CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    CLLocation *myLocation = [[CLLocation alloc]initWithLatitude:23.0225
                                                        longitude:72.5714];



    [geocoder reverseGeocodeLocation:myLocation
                   completionHandler:^(NSArray *placemarks, NSError *error) {

                       if (error) {
                           NSLog(@"Geocode failed with error: %@", error);
                           return;
                       }

                       if (placemarks && placemarks.count > 0)
                       {
                           CLPlacemark *placemark = placemarks[0];

                           NSDictionary *addressDictionary =
                           placemark.addressDictionary;

                           NSLog(@"%@ ", addressDictionary);
                           NSString *address = [addressDictionary
                                                objectForKey:(NSString *)kABPersonAddressStreetKey];
                           NSString *city = [addressDictionary
                                             objectForKey:(NSString *)kABPersonAddressCityKey];
                           NSString *state = [addressDictionary
                                              objectForKey:(NSString *)kABPersonAddressStateKey];


                           NSLog(@"%@ %@ %@ %@", address,city, state);
                       }

                   }];
5
Ketan Parmar On

This is because you are returning value before you get it in completion handler of reverseGeocodeLocation. Now, you can't return the value from any completion block so what you need to do is create your own completionblock and call it when you get your result something like,

 -(void)getLocation:(CLLocation *)locations withcompletionHandler : (void(^)(NSString *name))completionHandler{


CLGeocoder *geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:locations completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
    placemark = [placemarks lastObject];

    completionHandler(placemark.name);

}];

}

and call it like,

   [self  getLocation:location withcompletionHandler:^(NSString *name) {

    NSLog(@"your name : %@",name);  // or do whatever you want with name!
}];

Update :

If you want whole array in completion handler as you have mentioned in comment then your method should be like,

 -(void)getLocation:(CLLocation *)locations withcompletionHandler : (void(^)(NSArray *arr))completionHandler{



CLGeocoder *geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:locations completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks,
                                                               NSError * _Nullable error) {
   // placemark = [placemarks lastObject];

    completionHandler(placemarks);

}];

}

and you can call it like,

 [self getLocation:location withcompletionHandler:^(NSArray *arr) {

    // you will get whole array here in `arr`, now you can manipulate it according to requirement
    NSLog(@"your response array : %@",arr);

    CLPlacemark *placemark = [arr lastObject];

}];