Skip to content

Instantly share code, notes, and snippets.

@kwylez
Created March 1, 2012 19:13
Show Gist options
  • Save kwylez/1952410 to your computer and use it in GitHub Desktop.
Save kwylez/1952410 to your computer and use it in GitHub Desktop.
Forward geocoding support for ios4 and ios5
// Block param typedef
typedef void (^ForwardGeoCompletionBlock)(CLLocationCoordinate2D coords);
// Fetch Records Method
- (void)fetchForwardGeocodeAddress:(NSString *)address withCompletionHanlder:(ForwardGeoCompletionBlock)completion {
if (NSClassFromString(@"CLGeocoder")) {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLGeocodeCompletionHandler completionHandler = ^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(@"error finding placemarks: %@", [error localizedDescription]);
}
if (placemarks) {
[placemarks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CLPlacemark *placemark = (CLPlacemark *)obj;
NSLog(@"PLACEMARK: %@", placemark);
if ([placemark.country isEqualToString:@"United States"]) {
NSLog(@"********found coords for zip: %f %f", placemark.location.coordinate.latitude,placemark.location.coordinate.longitude);
if (completion) {
completion(placemark.location.coordinate);
}
*stop = YES;
}
}];
}
};
[geocoder geocodeAddressString:address completionHandler:completionHandler];
} else {
/**
* Since the request to grab the geocoded address is using NSString's initWithContentsOfURL
* we are going to make use of GCD and grab that async. I didn't put this in the
* method itself because there could be an instance where you would want to make a
* synchronous call. Better to have flexibility.
*
* Possible improvement could be to write another method that does the async
* loading for you. However, if you did it that way how would you be notified
* when the results returned. Possibly KVO?
*/
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
CLLocation *location = [address newGeocodeAddress];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(location.coordinate);
}
});
});
}
}
// NSString Category (JSONKit is dependency for project since there isn't a native parser in iOS4
@interface NSString (Additions)
- (CLLocation *)newGeocodeAddress;
@end
#import "NSString+Additions.h"
@implementation NSString (Additions)
- (CLLocation *)newGeocodeAddress {
__block CLLocation *location = nil;
NSString *gUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false", self];
gUrl = [gUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *infoData = [[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:gUrl]
encoding:NSUTF8StringEncoding
error:nil] autorelease];
if ((infoData == nil) || ([infoData isEqualToString:@"[]"])) {
return location;
} else {
NSDictionary *jsonObject = [infoData objectFromJSONString];
if (jsonObject == nil) {
return nil;
}
NSArray *result = [jsonObject objectForKey:@"results"];
[result enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *value = [[obj objectForKey:@"geometry"] valueForKey:@"location"];
location = [[CLLocation alloc] initWithLatitude:[[value valueForKey:@"lat"] doubleValue]
longitude:[[value valueForKey:@"lng"] doubleValue]];
*stop = YES;
}];
}
return location;
}
@end
// Request Execution
[[MyLocationManager sharedManager] fetchForwardGeocodeAddress:@"37415" withCompletionHanlder:^(CLLocationCoordinate2D coords) {
NSLog(@"found coords for zip: %f %f", coords.latitude, coords.longitude);
}];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment