Pages

Wednesday, 25 July 2012

Get country name from coordinates or coordinates from search term using Objective-C and Google API

One project I have been working on recently saw me messing around with Objective-C as I created an app using the MKMapView for interacting with Google Maps. I'm only hoping that when I release the app Apple aren't gonna be stupid and reject my app saying I might as well rewrite it using their new APIs as they're doing away with Google maps in iOS6. Oh well, we'll see...

Anyway, this time around I am posting a couple of methods that outline how I retrieve a country name by doing a JSON query passing in the latitude and longitude of a place, and secondly how I get the coordinates to a search term (a string).

As usual I'll let the code speak for itself...

To get the string name of a country from latitude and longitude, also with the ability to specify which language you get the country name back in...
// Do reverse geocode lookup on latitude/longitude to get country name based on specified locale
- (NSString*)getCountryNameFromCoordinates:(CLLocationCoordinate2D)coordinates locale:(NSString*)language;
{
    NSLog(@"Querying Google location API for %@ country name for latitude %f and longitude %f...", language, coordinates.latitude, coordinates.longitude);
    
    // Get JSON contents from Google API
    NSString *url = [[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false&language=%@", coordinates.latitude, coordinates.longitude, language] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"Query URL is: %@", url);
    NSError *error = nil;
    NSString *jsonString = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSUTF8StringEncoding error:&error];
    if (error != nil)
    {
        NSLog(@"Error doing reverse geocode lookup on %f, %f, lang=%@: %@", coordinates.latitude, coordinates.longitude, language, error.localizedDescription);
        return nil;
    }

    // Extract country by parsing JSON data
    SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
    error = nil;
    NSDictionary *jsonObjects = [jsonParser objectWithString:jsonString error:&error];
    if (error != nil)
    {
        NSLog(@"Error parsing JSON response to reverse geocode lookup: %@", jsonParser.error);
        
        [jsonParser release];
        [jsonObjects release];

        return nil;
    }
    NSDictionary *results = [jsonObjects objectForKey:@"results"];
    NSString *country = nil;
    for (NSDictionary *item in results)
    {
        if ([[item objectForKey:@"types"] containsObject:@"country"])
        {
            country = [[[item objectForKey:@"address_components"] objectAtIndex:0] objectForKey:@"long_name"];
            NSLog(@"Found matching country name: %@", country);
            [item release];
            break;
        }
        
        [item release];
    }
    if (country == nil) {
        NSLog(@"Couldn't find a matching country name");
        
        [jsonParser release];
        [jsonObjects release];
        [results release];
        [country release];
        
        return nil;
    }
    
    [jsonParser release];
    [jsonObjects release];
    [results release];
    
    return country;
}

And to center your map (or whatever behaviour you so desire) on the coordinates obtained from a search on a specified location string...


- (void)searchCoordinatesForAddress:(NSString *)inAddress
{
    NSLog(@"Querying Google location API for latitude/longitude coordinates for search term %@", inAddress);
    
    // Get JSON contents from Google API
    NSString *url = [[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false", inAddress] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"Query URL is: %@", url);
    NSError *error = nil;
    NSString *jsonString = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSUTF8StringEncoding error:&error];
    if (error != nil)
    {
        NSLog(@"Error doing coordinate lookup on %@: %@", inAddress, error.localizedDescription);
        return;
    }
    
    // Extract coordinates by parsing JSON data
    SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
    error = nil;
    NSDictionary *jsonObjects = [jsonParser objectWithString:jsonString error:&error];
    if (error != nil)
    {
        NSLog(@"Error parsing JSON response to extract coordinates: %@", jsonParser.error);

        [jsonParser release];
        [jsonObjects release];
        
        return;
    }
    NSArray *results;
    NSDictionary *location;
    @try {
        results = [jsonObjects objectForKey:@"results"];
        location = [[[results objectAtIndex:0] objectForKey:@"geometry"] objectForKey:@"location"];
    }
    @catch (NSException *exception) {
        NSLog(@"Could not find searched location's coordinates");
        [jsonParser release];
        [jsonObjects release];
        return;
    }

    // Get latitude and longitude as double values
    double longitude = 0.0;
    double latitude = 0.0;   
    NSNumber *lat = [location objectForKey:@"lat"];
    NSNumber *lng = [location objectForKey:@"lng"];
    latitude = [lat doubleValue];
    longitude = [lng doubleValue];
    [lat release];
    [lng release];
    
    [jsonParser release];
    [jsonObjects release];
    [results release];
    
    if (longitude == 0 && latitude == 0) {
        NSLog(@"Could not find searched location's coordinates");
        return;
    }
    NSLog(@"Coordinates found for searched location: %f %f", latitude, longitude);
    
    // I zoom my map to the area in question.
    [self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];
}

No comments:

Post a Comment