使用CLGeocoder将NSString纬度/经度坐标转换为城市、州和时区

4
我是一名有用的助手,可以为您翻译文本。

我有一个视图控制器,从应用程序委托中获取用户的纬度和经度坐标。这个很好用,但我还需要用户的城市、州和时区。我知道我应该使用CLGeocoder来实现这一点(请参见代码的最后一部分),但不知道如何将其组合起来。我只需要城市、州和时区的NSStrings。有人有任何指针或示例吗?谢谢!

在我的应用程序委托中,我使用CCLocationManager获取坐标,如下所示:

- (NSString *)getUserCoordinates
{
    NSString *userCoordinates = [NSString stringWithFormat:@"latitude: %f longitude: %f", 
    locationManager.location.coordinate.latitude, 
    locationManager.location.coordinate.longitude];
    locationManager = [[CLLocationManager alloc] init];
    locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
    [locationManager startUpdatingLocation];
    return userCoordinates;
}

- (NSString *)getUserLatitude
{
    NSString *userLatitude = [NSString stringWithFormat:@"%f", 
    locationManager.location.coordinate.latitude];
    return userLatitude;
}

- (NSString *)getUserLongitude
{
    NSString *userLongitude = [NSString stringWithFormat:@"%f", 
    locationManager.location.coordinate.longitude];
    return userLongitude;
}

在我的视图控制器中,我使用以下代码获取用户的纬度和经度作为NSString:

NSString *userLatitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate 
getUserLatitude];

NSString *userLongitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate 
getUserLongitude];

我想获取城市、州和时区信息。我知道需要使用CLGeocoder,但不知道如何将它们结合起来:

CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, 
NSError *error) {
    for (CLPlacemark * placemark in placemarks) {
        NSString *locality = [placemark locality];
    }
}
4个回答

12

Brandon,有几点需要注意:

1)CLLocationManager可能不会立即回应您对坐标的请求。您应该将您的视图控制器设置为CLLocationManager委托,然后当位置更新到来时(这将在locationManager:didUpdateLocations:方法中),然后您可以运行CLGeocoder方法。

2)

我写成了这个样子:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    NSLog( @"didUpdateLocation!");
    NSLog( @"latitude is %@ and longitude is %@", [self getUserLatitude], [self getUserLongitude]);

    CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:locationManager.location completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark * placemark in placemarks) {
            NSString * addressName = [placemark name];
            NSString * city = [placemark locality]; // locality means "city"
            NSString * administrativeArea = [placemark administrativeArea]; // which is "state" in the U.S.A.

            NSLog( @"name is %@ and locality is %@ and administrative area is %@", addressName, city, administrativeArea );
        }
    }];
}

获取位置的时区有点棘手。我猜在 iOS 中有一个 API 或一些示例代码可以获取它,但它不是 CLPlacemark API 的一部分。


最好将这个放在您的视图控制器中。但是请注意,如果您的视图控制器不可见或更重要的是不存在,请确保将位置管理器委托设置为 null,以便您不会遇到任何意外的错误行为。 - Michael Dautermann
好的,Michael - 我明白了。谢谢! - Brandon
嗨,Michael - 我实际上遇到了两个错误 - "no visible interface... declares the selector getUserLatitude" 和 "use of undeclared identifier locationManager"。 - Brandon

2
从经度和纬度的双精度值创建CLLocation。然后将该位置提供给reverseGeocodeLocation:completionHandler:。
还要注意,方法reverseGeocodeLocation:completionHandler:是异步的。
您还可以使用CLLocationManagerDelegate的locationManager:didUpdateHeading:异步更新是否有可用位置,这更好。
无论如何,按照您的方法,只需修改AppDelegate中的一些代码即可。
- (double)getUserLatitude
{
    return retrun locationManager.location.coordinate.latitude;
}

- (double)getUserLongitude
{
    retrun locationManager.location.coordinate.longitude;
}

-(CLLocationManager*) getLocationManager
{
    return locationManager;
}

现在创建一个位置对象。
double latt = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getUserLatitude];

double longt = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getUserLongitude];
CLLocation loc = [[CLLocation alloc] initWithLatitude:latt longitude:longt]

或者你可以直接从CLLocationManager获取位置对象。
CLLocation loc = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getLocationManager].location;

然后您可以使用您的代码将位置传入 reverseGeocodeLocation:completionHandler: 并获取 CLPlaceMark。
[geoCoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, 
NSError *error) {
    for (CLPlacemark * placemark in placemarks) {
        NSString *locality = [placemark locality];
        NSString * name =    [placemark name];
        NSString  *country  = [placemark country];
        /*you can put these values in some member vairables*/

        m_locality = [placemark locality];
        m_name =    [placemark name];
        m_country  = [placemark country];
    }
}

我不相信这会获取时区。我认为你需要一个外部API(非苹果)来获取它。 - Greg Maletic

0

虽然我没有时区问题的解决方案(我同意其他回答这个问题的人的看法 - 寻找非Apple API),但我想为那些好奇的人提供一个用Swift编写的答案:

func provideGeocodedStringForLocation(location: CLLocation, withCompletionHandler completionHandler: (String) -> ()) {
  let geocoder = CLGeocoder()
  geocoder.reverseGeocodeLocation(location) { (placemarks: [CLPlacemark]?, error: NSError?) -> Void in
    guard let placemarks = placemarks where placemarks.count > 0 && error == nil else {
      if let error = error { print(error.localizedDescription) }
      completionHandler("Earth")
      return
    }

    let city = placemarks[0].locality ?? ""
    let state: String
    if let adminArea = placemarks[0].administrativeArea {
      state = ", \(adminArea)"
    } else {
      state = ""
    }

    completionHandler("\(city)\(state)") // produces output similar to "Boulder, CO"
  }
}

// get the lat/long from your UIAppDelegate subclass
let latitude = CLLocationDegrees("40.0176")
let longitude = CLLocationDegrees("-105.28212")
let location = CLLocation(latitude: latitude, longitude: longitude)

provideGeocodedStringForLocation(location) { print($0) }

-1

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