【问题标题】:iPhone - Get City name from Latitude and LongtiudeiPhone - 从纬度和经度获取城市名称
【发布时间】:2012-05-09 12:00:34
【问题描述】:

我想在我的 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 Web 服务

-(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];
        }
    }
}

但是我得到的响应太长了,这意味着我仍然无法获取城市名称,因为在某些情况下,此 Web 服务会提供有关坐标的所有其他信息,期望城市名称。

谁能帮帮我?

【问题讨论】:

标签: iphone objective-c ios google-maps


【解决方案1】:

根据文档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];

编辑

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

【讨论】:

  • 有时此代码不起作用,请尝试找到一些替代解决方案
  • 不适合我我正在使用这个maps.google.com/maps/geo?q=37.785834,-122.406417&output=csv 输出是“610,0,0,0”
  • @HardikShah 你得到这个输出是因为你使用的是 csv。将其更改为 xmljson,例如 output=xml,它会告诉您这是旧的地理编码,而新的则不同。您还将在 xml 或 json 响应中获得新的地理编码链接。
  • @Chandni 你可以看到更新的评论,不要使用上面的功能,因为它已经停止工作了。
【解决方案2】:

我正在使用它并获取邮政编码和城市名称。修改了 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);

    }];

}

【讨论】:

    【解决方案3】:

    它对我有用:)

    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);
     }];
    

    【讨论】:

      【解决方案4】:
      //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
      

      抱歉我的英语不好,希望对你有帮助

      【讨论】:

        【解决方案5】:

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

        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"];
        

        【讨论】:

        【解决方案6】:
        - (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】:

          这很好,对我有用。

          我使用 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;
          }
          

          【讨论】:

            【解决方案8】:

            我改进了@Constantin Saulenco 很好的答案- json 的结果并不总是以相同的顺序排列 - 所以 city 并不总是在同一个索引中 - 这个函数将搜索正确的。 还添加了国家/地区。

            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];
            

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

                【解决方案10】:

                请检查以下功能

                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
                        })
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-12-09
                  • 2013-03-03
                  • 2011-09-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-10-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多