从地址获取纬度/经度

17

如何在使用iPhone SDK 3.x时,从用户输入的完整地址(包括街道、城市等)中获取纬度和经度?

9个回答

30

以下是 unforgiven 代码的更新、更紧凑的版本,使用了最新的 v3 API:

- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)address
{
    double latitude = 0, longitude = 0;
    NSString *esc_addr =  [address 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;
    return center;
}

该代码假设“location”的坐标先出现,例如在“viewport”坐标之前,因为它只取出“lng”和“lat”键下找到的第一个坐标。如果您担心这里使用的简单扫描技术,请随意使用适当的JSON扫描器(例如SBJSON)。


4
这种方法效果很好。我发现一个漏洞,可能是因为Google改变了响应格式。scanUpToString和scanString在":"前应该再加一个空格。应该像这样:scanUpToString:@""lat" :"和scanString:@""lat" :"(用于lat和lng两者)。 - cberkley
@cberkley 我已经做出了更改,但为了安全起见,扫描程序应该被更改为不在意纬度/经度和冒号之间的空格。我们永远不知道谷歌何时会再次“修复”这个糟糕的格式。事实上,'russes'版本可能更适合这种情况。 - Thomas Tempelmann
1
我发布了我的解决方案,因为在2011年字符串扫描器似乎无法工作。让SBJson解析Google的响应对于从斯坦福CS193在线课程学习iOS编码的初学者来说是有意义的。 - russes
如果您在地址参数中输入“test”会怎样? - Gajendra K Chauhan

8
您可以使用Google Geocoding(点击此处)来实现此功能。只需通过HTTP获取数据并解析即可(它可以返回JSON、KML、XML、CSV格式)。

7

这里有一个从谷歌获取纬度和经度的类似解决方案。注意:此示例使用SBJson库,您可以在github上找到:

+ (CLLocationCoordinate2D) geoCodeUsingAddress: (NSString *) address
{
    CLLocationCoordinate2D myLocation; 

// -- modified from the stackoverflow page - we use the SBJson parser instead of the string scanner --

        NSString       *esc_addr = [address stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
        NSString            *req = [NSString stringWithFormat: @"http://maps.google.com/maps/api/geocode/json?sensor=false&address=%@", esc_addr];
    NSDictionary *googleResponse = [[NSString stringWithContentsOfURL: [NSURL URLWithString: req] encoding: NSUTF8StringEncoding error: NULL] JSONValue];

    NSDictionary    *resultsDict = [googleResponse valueForKey:  @"results"];   // get the results dictionary
    NSDictionary   *geometryDict = [   resultsDict valueForKey: @"geometry"];   // geometry dictionary within the  results dictionary
    NSDictionary   *locationDict = [  geometryDict valueForKey: @"location"];   // location dictionary within the geometry dictionary

// -- you should be able to strip the latitude & longitude from google's location information (while understanding what the json parser returns) --

    DLog (@"-- returning latitude & longitude from google --");

    NSArray *latArray = [locationDict valueForKey: @"lat"]; NSString *latString = [latArray lastObject];     // (one element) array entries provided by the json parser
    NSArray *lngArray = [locationDict valueForKey: @"lng"]; NSString *lngString = [lngArray lastObject];     // (one element) array entries provided by the json parser

     myLocation.latitude = [latString doubleValue];     // the json parser uses NSArrays which don't support "doubleValue"
    myLocation.longitude = [lngString doubleValue];

    return myLocation;
}

4

更新版本,使用iOS JSON:

- (CLLocationCoordinate2D)getLocation:(NSString *)address {

    CLLocationCoordinate2D center;
    NSString *esc_addr =  [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSString *req = [NSString stringWithFormat:@"http://maps.google.com/maps/api/geocode/json?sensor=false&address=%@", esc_addr];
    NSData *responseData = [[NSData alloc] initWithContentsOfURL:
                        [NSURL URLWithString:req]];    NSError *error;
    NSMutableDictionary *responseDictionary = [NSJSONSerialization
                                               JSONObjectWithData:responseData
                                               options:nil
                                               error:&error];
    if( error )
    {
        NSLog(@"%@", [error localizedDescription]);
        center.latitude = 0;
        center.longitude = 0;
        return center;
    }
    else {
        NSArray *results = (NSArray *) responseDictionary[@"results"];
        NSDictionary *firstItem = (NSDictionary *) [results objectAtIndex:0];
        NSDictionary *geometry = (NSDictionary *) [firstItem objectForKey:@"geometry"];
        NSDictionary *location = (NSDictionary *) [geometry objectForKey:@"location"];
        NSNumber *lat = (NSNumber *) [location objectForKey:@"lat"];
        NSNumber *lng = (NSNumber *) [location objectForKey:@"lng"];

        center.latitude = [lat doubleValue];
        center.longitude = [lng doubleValue];
        return center;
    }
}

3
以下方法所做的就是您要求的。您需要插入您的Google地图密钥,以便它可以正确运行。
- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)address{

    int code = -1;
    int accuracy = -1;
    float latitude = 0.0f;
    float longitude = 0.0f;
    CLLocationCoordinate2D center;

    // setup maps api key
    NSString * MAPS_API_KEY = @"YOUR GOOGLE MAPS KEY HERE";

    NSString *escaped_address =  [address stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
    // Contact Google and make a geocoding request
    NSString *requestString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv&oe=utf8&key=%@&sensor=false&gl=it", escaped_address, MAPS_API_KEY];
    NSURL *url = [NSURL URLWithString:requestString];

    NSString *result = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error:NULL];
        if(result){
            // we got a result from the server, now parse it
            NSScanner *scanner = [NSScanner scannerWithString:result];
            [scanner scanInt:&code];
            if(code == 200){
                // everything went off smoothly
                [scanner scanString:@"," intoString:nil];
                [scanner scanInt:&accuracy];

                //NSLog(@"Accuracy: %d", accuracy);

                [scanner scanString:@"," intoString:nil];
                [scanner scanFloat:&latitude];
                [scanner scanString:@"," intoString:nil];
                [scanner scanFloat:&longitude];


                center.latitude = latitude;
                center.longitude = longitude;

                return center;


            }
            else{
                // the server answer was not the one we expected
                UIAlertView *alert = [[[UIAlertView alloc] 
                                       initWithTitle: @"Warning" 
                                       message:@"Connection to Google Maps failed"
                                       delegate:nil
                                       cancelButtonTitle:nil 
                                       otherButtonTitles:@"OK", nil] autorelease];

                [alert show];

                center.latitude = 0.0f;
                center.longitude = 0.0f;

                return center;


            }

        }
        else{
            // no result back from the server
            UIAlertView *alert = [[[UIAlertView alloc] 
                                   initWithTitle: @"Warning" 
                                   message:@"Connection to Google Maps failed"
                                   delegate:nil
                                   cancelButtonTitle:nil 
                                   otherButtonTitles:@"OK", nil] autorelease];

            [alert show];

            center.latitude = 0.0f;
            center.longitude = 0.0f;

            return center;
        }

    }

        center.latitude = 0.0f;
        center.longitude = 0.0f;

        return center;

}

这段代码现在不起作用,因为我的实时应用程序无法正常工作...!?! - Manish Jain

1

1
对于谷歌地图密钥解决方案,如上所述的不可原谅,难道不必使应用程序免费吗?根据谷歌的条款和条件:9.1 免费,公共访问您的地图 API 实现。您的地图 API 实现必须对用户普遍免费开放。
使用 SDK 中的地图工具包 3.0,可以轻松完成此操作。请参阅苹果的手册或按照以下步骤:https://developer.apple.com/documentation/mapkit

0
func geoCodeUsingAddress(address: NSString) -> CLLocationCoordinate2D {
    var latitude: Double = 0
    var longitude: Double = 0
    let addressstr : NSString = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=\(address)" as NSString
    let urlStr  = addressstr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
    let searchURL: NSURL = NSURL(string: urlStr! as String)!
    do {
        let newdata = try Data(contentsOf: searchURL as URL)
        if let responseDictionary = try JSONSerialization.jsonObject(with: newdata, options: []) as? NSDictionary {
            print(responseDictionary)
            let array = responseDictionary.object(forKey: "results") as! NSArray
            let dic = array[0] as! NSDictionary
            let locationDic = (dic.object(forKey: "geometry") as! NSDictionary).object(forKey: "location") as! NSDictionary
            latitude = locationDic.object(forKey: "lat") as! Double
            longitude = locationDic.object(forKey: "lng") as! Double
        }} catch {
    }
    var center = CLLocationCoordinate2D()
    center.latitude = latitude
    center.longitude = longitude
    return center
}

answer in latest swift 3.0 - Piyush Sinroja

0
- (void)viewDidLoad
{
    app=(AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSLog(@"%@", app.str_address);


    NSLog(@"internet connect");

    NSString *Str_address=_txt_zipcode.text;

    double latitude1 = 0, longitude1 = 0;
    NSString *esc_addr =  [ Str_address 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:&latitude1];
            if ([scanner scanUpToString:@"\"lng\" :" intoString:nil] && [scanner scanString:@"\"lng\" :" intoString:nil])
            {
                [scanner scanDouble:&longitude1];
            }
        }
    }


    //in #.hfile
   // CLLocationCoordinate2D lat;
   // CLLocationCoordinate2D lon;
   // float address_latitude;
   // float address_longitude;


    lat.latitude=latitude1;
    lon.longitude=longitude1;

    address_latitude=lat.latitude;
    address_longitude=lon.longitude;

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接