0

I am trying to do a forward geocode on a string, and it usually works ok, but for some locations, like "Vancouver" it returns null for the locality of the resulting placemark, but it does return the country, province, and coordinates. I even tried reverse geocoding the coordinate I found from forward geocoding, and although that didn't fail, it returned a different location, "Port Moody".

The weirdest part is that I tried running Vancouver through Apple's sample code for the Geocoder and it works just fine. The locality does not come up null.

Also, I was testing it out, and it suddenly started working, and then I checked again and it stopped working. What gives?

Here's my code. Doubt it will help much though.

-(BOOL) textFieldShouldReturn:(UITextField *)textField {
     CLGeocoder *geocoder = [[CLGeocoder alloc] init];

     [geocoder geocodeAddressString:textField.text completionHandler:^(NSArray *placemarks, NSError *error) {
    self.placemark = [[MKPlacemark alloc] initWithPlacemark:[placemarks objectAtIndex:0]];
    if (error) {
        NSLog(@"Geocode error %@",error.debugDescription);
        [self alertForFailedGeocode];
        return;
    }
    if (self.placemark.locality == nil || self.placemark.country == nil) {
        //eg if you search "Canada" you'll get a nil locality, and the coordinate is in the middle of nowhere.

        if (self.placemark.location) {
            [geocoder reverseGeocodeLocation:self.placemark.location completionHandler:^(NSArray *placemarks, NSError *error) {
                if (error) {
                    [self alertForFailedGeocode];
                    return;
                }

                self.placemark = [placemarks objectAtIndex:0];
                [self alertForConfirmGeocode:[self locationStringForPlacemark:self.placemark]];
                self.location = self.placemark.location;
                self.isUsingCurrentLocation = FALSE;
                return;
            }];
            return;
        }
        else {
            NSLog(@"Geocode failed BECAUSE nil locality or country or both");
            [self alertForFailedGeocode];
            return;
        }
    }

    NSLog(@"%d places found",placemarks.count);
    [self alertForConfirmGeocode:[self locationStringForPlacemark:self.placemark]];
    self.location = self.placemark.location;
    self.isUsingCurrentLocation = FALSE;
}];
return YES;

}

j0k
  • 22,600
  • 28
  • 79
  • 90
shim
  • 9,289
  • 12
  • 69
  • 108
  • Well, obviously for Canada locality will be null, but its null even for Singapore - which is annoying – MCKapur Aug 05 '13 at 10:17

1 Answers1

2

The Geocoding operations are not handled on the device and requires internet connection as they happen on cloud. It has its pros and cons.

Pros:

  1. Save your device resources, as the conversion is happening on Cloud.
  2. Apple can update their APIs on cloud as technology improves and that can give our apps better performance without even have to vchange anything in code.

Cons:

You would need a solid internet connection to access geocoding APIs.

Now coming to your condition, my guess is somehow due to internet connection, you are not able to use geocoding APIs completely. May be thats why you are not getting the locality.

The question is then how are you getting the country, province, and coordinates?

Well as it happens, the forward geocoder can get you the high level information such as country, region etc based on local device information but it requires internet connection to get more information such as locality etc.

Puneet Sharma
  • 9,369
  • 1
  • 27
  • 33
  • Great answer, although my internet seems to be fine. My only question then is why it works in the iOS Geocoder sample code? http://developer.apple.com/library/ios/#samplecode/GeocoderDemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS40011097 Essentially the same operation, same simulator, done around the same time, internet working fine, plenty of other locations working fine, but no city name when I search Vancouver (I'm yet to find other places that do this for me, but presumably it's more than just one) – shim Jul 25 '13 at 05:49
  • I tried your code, and it returned me locality. I am nonplussed. Could you please tell me the exact NSString you used in textfield.text. i used Vancouver it gave me locality. – Puneet Sharma Jul 25 '13 at 06:48
  • Used a variety of different variations on "Vancouver." Like I said the Apple sample code running on the same simulator seems to always work fine, but most of the time my code doesn't work. One time it seemed to start working fine but then I couldn't reproduce that. – shim Aug 05 '13 at 16:58
  • 1
    Your code seems to work well at my end. May I suggest including a delay of some time? Because it takes time for geocoding and it happens on another thread. You must be calling some method to create/mark annotation. You could call that method after some delay [self performSelector:@select(createAnnotation:) withObject:nil afterDelay:5.0]; You could show an activity indicator view until the method executes... – Puneet Sharma Aug 06 '13 at 04:29