如何从iphone sdk中的城市名称获取位置(坐标)?

时间:2011-05-19 13:55:23

标签: iphone google-maps

朋友,

因为我们在android中有google api的geocoder getfromlocation(locationname,maximumResults)函数。

我没有在iphone sdk中看到这样的功能来从城市名称中获取纬度和经度值。

任何人都指导我如何实现此功能? 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:25)

iOS< 5

没有地理编码API。你需要问谷歌: 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&gt; = 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:地址簿的地址簿键和值。
  • region
  • inlandWater
  • 海洋
  • areasOfInterest

答案 1 :(得分:4)

使用以下方法从城市名称中查找位置的坐标:

来源:(http://sickprogrammersarea.blogspot.in/2014/03/programmatically-find-co-ordinates-of.html

-(CLLocationCoordinate2D) getLocationFromAddressString: (NSString*) addressStr {
double latitude = 0, longitude = 0;
NSString *esc_addr =  [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat:@"http://maps.google.com/maps/api/geocode/json?sensor=false&address=%@", esc_addr];
NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:req] encoding:NSUTF8StringEncoding error:NULL];
if (result) {
    NSScanner *scanner = [NSScanner scannerWithString:result];
    if ([scanner scanUpToString:@"\"lat\" :" intoString:nil] && [scanner scanString:@"\"lat\" :" intoString:nil]) {
        [scanner scanDouble:&latitude];
        if ([scanner scanUpToString:@"\"lng\" :" intoString:nil] && [scanner scanString:@"\"lng\" :" intoString:nil]) {
            [scanner scanDouble:&longitude];
        }
    }
}
CLLocationCoordinate2D center;
center.latitude=latitude;
center.longitude = longitude;
NSLog(@"View Controller get Location Logitute : %f",center.latitude);
NSLog(@"View Controller get Location Latitute : %f",center.longitude);
return center;

}

希望它会有所帮助。

答案 2 :(得分:0)

您可以在其他一些答案中使用Google地理编码器API。 或者,您可以使用geonames.org提供的地理编码服务。

您可以从ILGeoNames下载我的GitHub包装类。它们提供了一个Objective C API,用于使用geonames.org搜索功能。除此之外,您还可以按名称搜索城市并获取其坐标。