block until reverseGeocode has returned

I am trying to find a user’s location from a coordinate to save into my database.

To find the location name I am using reverseGeocode. However since it is a block method my self.locationName will return (and save as nil) into the database. So I have tried to find a solution to the problem, and tried to put together the following solution using semaphores to try and block until I get a locationName I can save, but the app just hangs when the save button is pressed. Should I even be going about this problem in this way or is there a better way?

  • gpus_ReturnGuiltyForHardwareRestart
  • Querying iOS Keychain using Swift
  • Search Bar disappeared from view while typing
  • Any way to install app to iPhone 4 with Xcode 8 beta?
  • Retrieve Facebook pages likes using custom login button
  • Swift - How do I get the file path inside a folder
  •  dispatch_semaphore_t semaphore;
    
     - (void)reverseGeocode:(CLLocation *)location {
         CLGeocoder *geocoder = [[CLGeocoder alloc] init];
        [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks,                    NSError *error) {
    
         NSLog(@"Finding address");
         if (error) {
         NSLog(@"Error %@", error.description);
         } else {
         CLPlacemark *placemark = [placemarks lastObject];
         self.locationName = [NSString stringWithFormat:@"%@", ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO)];
         dispatch_semaphore_signal(semaphore);         
                }
         }];
         }
    
    
    
    -(NSString *)findLocation:(CLLocation *)startingLocation
    {
    semaphore = dispatch_semaphore_create(0);
    [self reverseGeocode:startingLocation];
     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //should maybe timeout
    return self.locationName;
    }
    

    Solutions Collect From Internet About “block until reverseGeocode has returned”

    You are thinking about this all wrong. That is not how asynchronous code works. Do NOT block until the code returns. Just launch the code to start the reverse geocode, and finish up. Now when the reverse geocode finishes, it calls you back and you can do whatever you want with the returned info. That is the whole point of the completion handler: it doesn’t run until the reverse geocode has completed.

    Just get rid of the semaphores and let things happen asynchronously. Here is a complete example without the secondary method:

    CLLocation* loc = userLocation.location;
    [geo reverseGeocodeLocation:loc
              completionHandler:^(NSArray *placemarks, NSError *error)
      {
          if (placemarks) {
              CLPlacemark* p = [placemarks objectAtIndex:0];
              NSLog(@"%@", p.addressDictionary); // do something with address
          }
      }];
    

    As you’ve already been told, if you really want to call this from another method and then do something further, then pass a block to this method and call the block inside the completion handler. That means the block you passed is code that will run when the geocoding has completed, which is exactly what you want – without semaphores and without freezing the app.

    Freezing the app is bad form and the WatchDog will kill your app dead if you do it for too long. Just don’t do it.