1

I have an array of coordinates that I step through with a for loop. I would like to place annotations on a map for each location and have the subtitle for the callout be the address of the coordinate, found by using reverseGeocodeLocation In the for loop, I call the reverseGeocodeLocation method, and inside the completion block I create the annotation and display it on the map. However, when I run the app, only one annotation shows up. I went in the debugger, and the completion block is only getting called once (for two calls to the reverseGeocodeLocation method). Any suggestions to fix this?

My for loop:

for(int i = 0; i < [locations count]; i++)
{
    CLLocation *location = [locations objectAtIndex:i];
    __block NSString *info;
    NSLog(@"Resolving the Address");
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
    {
        NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
        if (error == nil && [placemarks count] > 0)
        {
            placemark = [placemarks lastObject];
            info = [NSString stringWithFormat:@"%@ %@ %@ %@, %@",
                    placemark.subThoroughfare, placemark.thoroughfare,
                    placemark.postalCode, placemark.locality,
                    placemark.administrativeArea];
            [self remainderOfMethod:location withAddress:info atIndex:i];
        }
        else
        {
            NSLog(@"%@", error.debugDescription);
        }
    } ];
}

And the method called at the completion block:

- (void) remainderOfMethod: (CLLocation *)location withAddress:(NSString *)info atIndex: (int)i
{
     MKPointAnnotation* annotation = [[MKPointAnnotation alloc] init];
     if (location != nil)
     {
         [annotation setSubtitle:[NSString stringWithFormat:@"%@", info]];
         annotation.coordinate = location.coordinate;
         [self.mapView addAnnotation:annotation];
     }
}

Thanks!

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Drew K.
  • 177
  • 1
  • 1
  • 7

1 Answers1

2

From the official Apple documentation:

After initiating a reverse-geocoding request, do not attempt to initiate another reverse- or forward-geocoding request

You can find the docs here: https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLGeocoder_class/Reference/Reference.html#//apple_ref/occ/instm/CLGeocoder/reverseGeocodeLocation:completionHandler:

One way to solve it is to do only one request at a time in a recursive method that pops a location from a stack (or array) on each iteration.

Even in that case, consider what Apple has to say about it:

Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may cause some of the requests to fail

So you may want to request geocoding on demand, for example when a user taps on an annotation.

Matías R
  • 2,195
  • 1
  • 14
  • 12
  • When a user taps on an annotation is a good idea! Thanks! However, I do allow the user to see all the locations in a table view, in which case i need to load the data all at once. Any ideas for that? – Drew K. Apr 15 '14 at 00:38
  • In that case you can use a recursive method. The difference is that in a for loop, there will be many concurrent request for geolocation. If you do it recursively by invoking the method once the completionHandler finished, you'll be sure to have only one active request for geocoding. Anyway, this doesn't solve the limitation that Apple puts in place for each app. I don't really know what the limit is. – Matías R Apr 15 '14 at 00:44
  • Thanks! I'll check documentation for the limit – Drew K. Apr 15 '14 at 00:46