1

I am trying to return the user's state using reverseGeocodeLocation. I am using this code to pull the user's location from another view.

NSString *userState =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate     
getAddressFromLocation]; 

I am getting the following error: 'NSInvalidArgumentException', reason: '-[PDCAppDelegate getAddressFromLocation]: unrecognized selector sent to instance. The code I am using in PDCAppDelegate to return the address is below.

-(NSString *)getAddressFromLocation:(CLLocation *)location {
NSString *address;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError 
*error)
 {
     if(placemarks && placemarks.count > 0)
     {
         CLPlacemark *placemark= [placemarks objectAtIndex:0];

         NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [placemark 
subThoroughfare],[placemark thoroughfare],[placemark locality], [placemark 
administrativeArea]];

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

 }];

return address;
}

Anyone know how to fix this? Thank you!

3
  • Did you add your function to header?
    – Misha
    Commented Dec 17, 2012 at 8:01
  • I have this in my appDelegate header: -(NSString *) getAddressFromLocation;
    – Brandon
    Commented Dec 17, 2012 at 8:04
  • i don't know if i need to put the :(CLLocation *)location part though
    – Brandon
    Commented Dec 17, 2012 at 8:04

1 Answer 1

2

The CLGeocoder method reverseGeocodeLocation:completionHandler: runs asynchronously. That means you can't return the address from getAddressFromLocation: because the address is simply not set when you return from this method.

When the geocoder received the address (or the call caused an error) it will run the completionHandler. You have to set, or show the address from within the completion handler.

Easiest would be to send a NSNotification, probably not the best way though:

-(void)getAddressFromLocation:(CLLocation *)location {
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if (!placemarks) {
             // handle error
         }

         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *placemark= [placemarks objectAtIndex:0];
             NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [placemark subThoroughfare],[placemark thoroughfare],[placemark locality], [placemark administrativeArea]];

             // you have the address.
             // do something with it.
             [[NSNotificationCenter defaultCenter] postNotificationName:@"MBDidReceiveAddressNotification" 
                  object:self 
                userInfo:@{ @"address" : address }];
         }
     }];
}
4
  • thanks! could I store it in NSuserdefaults? NSString *valueToSave = address; [[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"address"];
    – Brandon
    Commented Dec 17, 2012 at 8:07
  • sure, once you have it you can do whatever you want with the address. You just have to find a way to tell the rest of your app that you received the address. Keep in mind that you don't know how long it will take until the address is found. It could be within a couple of milliseconds, or take half a minute. Commented Dec 17, 2012 at 8:09
  • Oh ok got it. Do I need to tell the appDelegate something for it to run this bit of code? or will it run automatically?
    – Brandon
    Commented Dec 17, 2012 at 8:10
  • If you want to use the notification pattern you have to register for the notification in your AppDelegate. Please read Notification Programming Topics Commented Dec 17, 2012 at 8:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.