Ответ 1
iOS < 5
Отсутствует API геокодирования. Вы должны спросить Google: http://maps.googleapis.com/maps/api/geocode/json?address=YOURADDRESS&sensor=true и проанализировать результат, используя JSONKit.
Что-то вроде этого:
-(CLLocation*) geocodeAddress:(NSString*) address {
NSLog(@"Geocoding address: %@", address);
// don't make requests faster than 0.5 seconds
// Google may block/ban your requests if you abuse the service
double pause = 0.5;
NSDate *now = [NSDate date];
NSTimeInterval elapsed = [now timeIntervalSinceDate:self.lastPetition];
self.lastPetition = now;
if (elapsed>0.0 && elapsed<pause){
NSLog(@" Elapsed < pause = %f < %f, sleeping for %f seconds", elapsed, pause, pause-elapsed);
[NSThread sleepForTimeInterval:pause-elapsed];
}
// url encode
NSString *encodedAddress = (NSString *) CFURLCreateStringByAddingPercentEscapes(
NULL, (CFStringRef) address,
NULL, (CFStringRef) @"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
NSString *url = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=true", encodedAddress];
//NSLog(@" url is %@", url);
[encodedAddress release];
// try twice to geocode the address
NSDictionary *dic;
for (int i=0; i<2; i++) { // two tries
HttpDownload *http = [HttpDownload new];
NSString *page = [http pageAsStringFromUrl:url];
[http release];
dic = [JsonParser parseJson:page];
NSString *status = (NSString*)[dic objectForKey:@"status"];
BOOL success = [status isEqualToString:@"OK"];
if (success) break;
// Query failed
// See http://code.google.com/apis/maps/documentation/geocoding/#StatusCodes
if ([status isEqualToString:@"OVER_QUERY_LIMIT"]){
NSLog(@"try #%d", i);
[NSThread sleepForTimeInterval:1];
} else if ([status isEqualToString:@"ZERO_RESULTS"]){
NSLog(@" Address unknown: %@", address);
break;
} else {
// REQUEST_DENIED: no sensor parameter. Shouldn't happen.
// INVALID_REQUEST: no address parameter or empty address. Doesn't matter.
}
}
// if we fail after two tries, just leave
NSString *status = (NSString*)[dic objectForKey:@"status"];
BOOL success = [status isEqualToString:@"OK"];
if (!success) return nil;
// extract the data
{
int results = [[dic objectForKey:@"results"] count];
if (results>1){
NSLog(@" There are %d possible results for this adress.", results);
}
}
NSDictionary *locationDic = [[[[dic objectForKey:@"results"] objectAtIndex:0] objectForKey:@"geometry"] objectForKey:@"location"];
NSNumber *latitude = [locationDic objectForKey:@"lat"];
NSNumber *longitude = [locationDic objectForKey:@"lng"];
NSLog(@" Google returned coordinate = { %f, %f }", [latitude floatValue], [longitude floatValue]);
// return as location
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitude doubleValue] longitude:[longitude doubleValue]];
return [location autorelease];
}
+(NSDictionary*) parseJson:(NSString*) jsonString {
NSDictionary *rootDict = nil;
NSError *error = nil;
@try {
JKParseOptionFlags options = JKParseOptionComments | JKParseOptionUnicodeNewlines;
rootDict = [jsonString objectFromJSONStringWithParseOptions:options error:&error];
if (error) {
warn(@"%@",[error localizedDescription]);
}
NSLog(@" JSONKit: %d characters resulted in %d root node", [jsonString length], [rootDict count]);
} @catch (NSException * e) {
// If data is 0 bytes, here we get: "NSInvalidArgumentException The string argument is NULL"
NSLog(@"%@ %@", [e name], [e reason]);
// abort
rootDict = nil;
}
return rootDict;
}
iOS >= 5
iOS 5 имеет API-интерфейс геокодирования:
CLGeocoder* gc = [[CLGeocoder alloc] init];
[gc geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error)
{
if ([placemarks count]>0)
{
// get the first one
CLPlacemark* mark = (CLPlacemark*)[placemarks objectAtIndex:0];
double lat = mark.location.coordinate.latitude;
double lng = mark.location.coordinate.longitude;
}
}];
Объект CLPlacemark имеет следующие свойства:
- имя
- addressDictionary: клавиши и значения адресной книги для метки.
- ISOcountryCode
- Страна
- PostalCode
- administrativeArea
- subAdministrativeArea
- местонахождение
- subLocality
- проезд: Уличный адрес.
- subThoroughfare: клавиши и значения адресной книги для метки.
- регион
- inlandWater
- океан
- areasOfInterest