iPhone - 从纬度和经度获取城市名称

时间:2012-05-09 12:00:34

标签: iphone objective-c ios google-maps

我想在我的iPhone应用程序中获取当前城市名称。

我目前正在使用CLLocationManager获取纬度和经度,而不是将我的坐标传递给CLGeocoder。

    CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark * placemark in placemarks) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Current City" message:[NSString stringWithFormat:@"Your Current City:%@",[placemark locality]] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil];
            [alert  show];
        }  
    }];

这在iOS 5.0中运行良好,但在iOS 4.3中无效。

作为替代方案,我开始使用Google网络服务

-(void)findLocationFor:(NSString *)latitudeStr 
          andLontitude:(NSString *)longtitudeStr{
    if ([self connectedToWiFi]){
        float latitude  = [latitudeStr floatValue];
        float longitude = [longtitudeStr floatValue];
        NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
                                           [NSString stringWithFormat:@"%f,%f", latitude, longitude], @"latlng", nil];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://maps.googleapis.com/maps/api/geocode/json"]];
        [parameters setValue:@"true" forKey:@"sensor"];
        [parameters setValue:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] forKey:@"language"];
        NSMutableArray *paramStringsArray = [NSMutableArray arrayWithCapacity:[[parameters allKeys] count]];

        for(NSString *key in [parameters allKeys]) {
            NSObject *paramValue = [parameters valueForKey:key];
            [paramStringsArray addObject:[NSString stringWithFormat:@"%@=%@", key, paramValue]];
        }

        NSString *paramsString = [paramStringsArray componentsJoinedByString:@"&"];
        NSString *baseAddress = request.URL.absoluteString;
        baseAddress = [baseAddress stringByAppendingFormat:@"?%@", paramsString];
        [request setURL:[NSURL URLWithString:baseAddress]];

        NSError        *error    = nil;
        NSURLResponse  *response = nil;
        NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
        if (response == nil) {
            if (error != nil) {
            }
        }
        else {
            NSDictionary *responseDict = [returnData objectFromJSONData];
            NSArray *resultsArray = [responseDict valueForKey:@"results"]; 
            NSMutableArray *placemarksArray = [NSMutableArray arrayWithCapacity:[resultsArray count]];
            for(NSDictionary *placemarkDict in resultsArray){
                NSDictionary *coordinateDict = [[placemarkDict valueForKey:@"geometry"] valueForKey:@"location"];

                float lat = [[coordinateDict valueForKey:@"lat"] floatValue];
                float lng = [[coordinateDict valueForKey:@"lng"] floatValue];

                NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
                [dict setObject:[NSString stringWithFormat:@"%.f",lat] forKey:@"latitude"];
                [dict setObject:[NSString stringWithFormat:@"%.f",lng] forKey:@"longitude"];
                [dict setObject:[placemarkDict objectForKey:@"formatted_address"] forKey:@"address"];

                [placemarksArray addObject:dict];
                [dict release];
            }
            NSDictionary *placemark = [placemarksArray objectAtIndex:0];
        }
    }
}

但我得到的回复太长,意味着我仍然无法获得城市名称,因为在某些情况下,这个网络服务会提供有关坐标的所有其他信息,希望城市名称。

任何人都可以帮助我吗?

10 个答案:

答案 0 :(得分:23)

根据文档CLGeocoder在iOS5下无效。你需要采取另一种方式来支持iOS4和iOS5。

您可以查看MKReverseGeocoder,但在iOS5中已弃用,但仍可用于此目的。如需确认,您可以查看so called question

+(NSString *)getAddressFromLatLon:(double)pdblLatitude withLongitude:(double)pdblLongitude
{
    NSString *urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%f,%f&output=csv",pdblLatitude, pdblLongitude];
    NSError* error;
    NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
    locationString = [locationString stringByReplacingOccurrencesOfString:@"\"" withString:@""];
    return [locationString substringFromIndex:6];
}

您可以使用此功能从纬度,经度获取地址。您可以根据要求进行更改。我们把它作为Class方法,所以我们可以直接使用它作为

NSString *strAddressFromLatLong = [CLassName getAddressFromLatLon:37.484848 withLongitude:74.48489];

修改

请停止使用上述功能,因为它已在评论中报告已停止工作(未经我测试)。我建议您开始使用SVGeocoder

答案 1 :(得分:13)

我正在使用它并获取邮政编码和城市名称。修改了Janak添加的方法。

- (void) getAddressFromLatLon:(CLLocation *)bestLocation
{
    NSLog(@"%f %f", bestLocation.coordinate.latitude, bestLocation.coordinate.longitude);
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:bestLocation
                   completionHandler:^(NSArray *placemarks, NSError *error)
    {
        if (error){
            NSLog(@"Geocode failed with error: %@", error);
            return;
        }
        CLPlacemark *placemark = [placemarks objectAtIndex:0];
        NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
        NSLog(@"locality %@",placemark.locality);
        NSLog(@"postalCode %@",placemark.postalCode);

    }];

}

答案 2 :(得分:9)

它对我有用:)

CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:26.93611 longitude:26.93611];

[ceo reverseGeocodeLocation: loc completionHandler:
 ^(NSArray *placemarks, NSError *error) {
     CLPlacemark *placemark = [placemarks objectAtIndex:0];
     NSLog(@"placemark %@",placemark);
     //String to hold address
     NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];
     NSLog(@"addressDictionary %@", placemark.addressDictionary);

     NSLog(@"placemark %@",placemark.region);
     NSLog(@"placemark %@",placemark.country);  // Give Country Name
     NSLog(@"placemark %@",placemark.locality); // Extract the city name
     NSLog(@"location %@",placemark.name);
     NSLog(@"location %@",placemark.ocean);
     NSLog(@"location %@",placemark.postalCode);
     NSLog(@"location %@",placemark.subLocality);

     NSLog(@"location %@",placemark.location);
     //Print the location to console
     NSLog(@"I am currently at %@",locatedAt);
 }];

答案 3 :(得分:5)

//Place below parser code where you are reading latlng and place your latlng in the url
NSXMLParser *parser = [[NSXMLParser alloc]initWithContentsOfURL:[NSURL URLWithString:@"http://maps.googleapis.com/maps/api/geocode/xml?latlng=40.714224,-73.961452&sensor=false"]];
[parser setDelegate:self];
[parser parse];

// Below are the delegates which will get you the exact address easyly
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{    
    if([elementName isEqualToString:@"formatted_address"]){
        got = YES; //got is a BOOL
    }
}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if(got){
        NSLog(@"the address is = %@",string);
    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
}

//what we are doing is using xmlparser to parse the data which we get through the google map api copy above link and use in browser you will see the xml data brought

抱歉,我的英语不好希望能帮到你

答案 4 :(得分:3)

在此处尝试此请求,您会找到有关当前位置,街道/城市/地区名称,门牌号码的所有数据,但您的请求只需粘贴即可。

NSString *urlString = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",pdblLatitude, pdblLongitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];

NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSDictionary *dic = [[json objectForKey:kResults] objectAtIndex:0];
NSString *cityName = [[[dic objectForKey:@"address_components"] objectAtIndex:1] objectForKey:@"long_name"];

答案 5 :(得分:2)

这很好,对我有用。

我使用CLLocationManager获取纬度和经度,而不是将我的坐标传递给CLGeocoder。

import @corelocation  and for getting city,country #import <AddressBook/AddressBook.h>
    -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
    CLLocation *location=[locations lastObject];
        CLGeocoder *geocoder=[[CLGeocoder alloc]init];

        CLLocationCoordinate2D coord;
        coord.longitude = location.coordinate.longitude;
        coord.latitude = location.coordinate.latitude;
        // or a one shot fill
        coord = [location coordinate];
        NSLog(@"longitude value%f", coord.longitude);
        NSLog(@"latitude value%f", coord.latitude);
        [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
            CLPlacemark *placemark = placemarks[0];
            NSDictionary *addressDictionary = [placemark addressDictionary];
            city = addressDictionary[(NSString *)kABPersonAddressCityKey];
            stateloc = addressDictionary[(NSString *)kABPersonAddressStateKey];
            country = placemark.country;


            NSLog(@"city%@/state%@/country%@",city,stateloc,country);
           [self getImagesFromServer:city];

        }];

        [self stopSignificantChangesUpdates];

    }

- (void)stopSignificantChangesUpdates
{
    [self.locationManager stopUpdatingLocation];
    self.locationManager = nil;
}

答案 6 :(得分:1)

- (void)reverseGeocode:(CLLocation *)location {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
    NSLog(@"Finding address");
    if (error) {
        NSLog(@"Error %@", error.description);
    } else {
        CLPlacemark *placemark = [placemarks lastObject];
        self.myAddress.text = [NSString stringWithFormat:@"%@", ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO)];
    }
}];
}

答案 7 :(得分:1)

我改进了@Constantin Saulenco很棒的答案 - json导致并不总是以相同的顺序排序 - 因此city并不总是在同一个索引 - 这个func将搜索正确的索引。 也增加了国家。

NSString *urlString = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",location.coordinate.latitude, location.coordinate.longitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];

NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSDictionary *dic = [[json objectForKey:@"results"] objectAtIndex:0];
NSArray* arr = [dic objectForKey:@"address_components"];
//Iterate each result of address components - find locality and country
NSString *cityName;
NSString *countryName;
for (NSDictionary* d in arr)
{
    NSArray* typesArr = [d objectForKey:@"types"];
    NSString* firstType = [typesArr objectAtIndex:0];
    if([firstType isEqualToString:@"locality"])
        cityName = [d objectForKey:@"long_name"];
    if([firstType isEqualToString:@"country"])
        countryName = [d objectForKey:@"long_name"];

}

NSString* locationFinal = [NSString stringWithFormat:@"%@,%@",cityName,countryName];

答案 8 :(得分:0)

我找到了这段代码,它对我有用: https://gist.github.com/flyworld/4222448

只需将placemark.ISOcountryCode更改为placemark.locality

答案 9 :(得分:0)

请检查波纹管功能

func getDataCity(tmpLat:Double,tmpLong:Double) {

    let tmpCLGeocoder = CLGeocoder.init()
    if tmpLat > 0 , tmpLong > 0
    {
        let tmpDataLoc = CLLocation.init(latitude: tmpLat, longitude: tmpLong)

        tmpCLGeocoder.reverseGeocodeLocation(tmpDataLoc, completionHandler: {(placemarks,error) in

            guard let tmpPlacemarks = placemarks else{
                return
            }
            let placeMark = tmpPlacemarks[0] as CLPlacemark

            guard let strLocality = placeMark.locality else{
                return
            }
            // strLocality is your city
            guard let strSubLocality = placeMark.subLocality else{

                return
            }
            // strSubLocality is your are of city
        })
    }
}