0

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.

sazid008
  • 175
  • 2
  • 14
  • print `placemark.name` below the `lacemark = [placemarks lastObject];` line(in completion handler)and tell me it will gives any value or not ! – Ketan Parmar Dec 19 '16 at 07:20
  • NSLog(@"addressDictionary %@", placemark.addressDictionary); its print address of your co ordinates . in side [geocoder reverseGeocodeLocation:locations completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) { placemark = [placemarks lastObject]; }]; – Himanshu Moradiya Dec 19 '16 at 07:26
  • Right, but I want to use the value out of block for each call of the method. @Lion – sazid008 Dec 19 '16 at 09:15

3 Answers3

1

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];

}];
Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
  • Same problem I got the name only inside the block `[self getLocation:location withcompletionHandler:^(NSString *name) {}];` but I need to update currentLocation. @Lion – sazid008 Dec 19 '16 at 10:22
  • then what you want ? you can add more parameters to method if you want other things also. I am not getting you clearly!! what you want to achieve exactly? – Ketan Parmar Dec 19 '16 at 10:52
  • Ok, let me clear. `currentLocation` is declared outside the block `[self getLocation:location withcompletionHandler:^(NSString *name) {}];`. As a result I can't get the `name` outside the block `[self getLocation:location withcompletionHandler:^(NSString *name) {}];` and can't update my `currentLocation`. But I need to update `currentLocation` for my further operation. – sazid008 Dec 19 '16 at 13:00
  • but how `getLocation` method will give current location ?? you are passing location and it is returning address (reverse geocoding! ), then how you expecting current location from it ???? – Ketan Parmar Dec 19 '16 at 13:23
  • Actually I am talking about that address. I just want to use that address by `currentLocation`. Now my question is can I use that address outside of the block? – sazid008 Dec 20 '16 at 04:38
0

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.

Gurdev Singh
  • 1,996
  • 13
  • 11
  • Exactly. I get value within the block but not outside. Can you show me how can I update my `currentLocation` with the location data of photo in completion handler. I tried but failed to update. @Gurdev – sazid008 Dec 19 '16 at 09:39
  • You should change the `getLocation()` to return `void` and when your completion handler block is executed the `placemark ` object will have the value of location found with `reverseGeocodeLocation()`. There after you can access its value. Let me know if any more help is required. – Gurdev Singh Dec 19 '16 at 10:14
-1

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);
                       }

                   }];
Darshan
  • 2,272
  • 3
  • 31
  • 43
  • 1
    Don't just post code. Please explain what was wrong and explain how your answers solves the issue. – rmaddy Dec 19 '16 at 07:19