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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…