16

试图从我从 CLGeocoder 获得的 AddressDictionary 获取格式化地址。使用以下代码没有结果:

subtitle = [NSString stringWithString:[[addressDict objectForKey:@"FormattedAddressLines"]objectAtIndex:0]];

也试过:

subtitle = [[[ABAddressBook sharedAddressBook] formattedAddressFromDictionary:placemark.addressDictionary] string];

但此代码似乎仅适用于 Mac OS X。

编译器询问 ABAdressBook,但我导入了两个头文件。

#import <AddressBook/ABAddressBook.h>
#import <AddressBook/AddressBook.h>
4

10 回答 10

40

addressDictionary物业的文件说:

您可以格式化此字典的内容以获得完整的地址字符串,而不是自己构建地址。要格式化字典,请使用地址簿 UI 函数参考中所述的 ABCreateStringWithAddressDictionary 函数。

所以添加并导入AddressBookUI框架并尝试:

subtitle = 
    ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO);
于 2011-10-21T12:16:44.917 回答
24

在 iOS 6.1 下进行一些挖掘后,我发现 CLPlacemark 地址字典包含一个预先格式化的地址:

CLLocation *location = [[CLLocation alloc]initWithLatitude:37.3175 longitude:-122.041944];
[[[CLGeocoder alloc]init] reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
    CLPlacemark *placemark = placemarks[0];
    NSArray *lines = placemark.addressDictionary[ @"FormattedAddressLines"];
    NSString *addressString = [lines componentsJoinedByString:@"\n"];
    NSLog(@"Address: %@", addressString);
}];

我还找不到有关此的文档,但它适用于我测试的所有地址。

于 2013-08-11T21:12:04.517 回答
19

正如 Martyn Davis 所强调的那样,ABCreateStringWithAddressDictionary在 iOS 9 中已弃用。

您可以使用下面的函数将 转换addressDictionary为较新的CNMutablePostalAddress,然后CNPostalAddressFormatter只要您导入Contacts框架,就可以使用 来生成本地化字符串。

斯威夫特 3.x

// Convert to the newer CNPostalAddress
func postalAddressFromAddressDictionary(_ addressdictionary: Dictionary<NSObject,AnyObject>) -> CNMutablePostalAddress {
   let address = CNMutablePostalAddress()

   address.street = addressdictionary["Street" as NSObject] as? String ?? ""
   address.state = addressdictionary["State" as NSObject] as? String ?? ""
   address.city = addressdictionary["City" as NSObject] as? String ?? ""
   address.country = addressdictionary["Country" as NSObject] as? String ?? ""
   address.postalCode = addressdictionary["ZIP" as NSObject] as? String ?? ""

   return address
}

// Create a localized address string from an Address Dictionary
func localizedStringForAddressDictionary(addressDictionary: Dictionary<NSObject,AnyObject>) -> String {
    return CNPostalAddressFormatter.string(from: postalAddressFromAddressDictionary(addressDictionary), style: .mailingAddress)
}

斯威夫特 2.x

import Contacts

// Convert to the newer CNPostalAddress
func postalAddressFromAddressDictionary(addressdictionary: Dictionary<NSObject,AnyObject>) -> CNMutablePostalAddress {

    let address = CNMutablePostalAddress()

    address.street = addressdictionary["Street"] as? String ?? ""
    address.state = addressdictionary["State"] as? String ?? ""
    address.city = addressdictionary["City"] as? String ?? ""
    address.country = addressdictionary["Country"] as? String ?? ""
    address.postalCode = addressdictionary["ZIP"] as? String ?? ""

    return address
}

// Create a localized address string from an Address Dictionary
func localizedStringForAddressDictionary(addressDictionary: Dictionary<NSObject,AnyObject>) -> String {

    return CNPostalAddressFormatter.stringFromPostalAddress(postalAddressFromAddressDictionary(addressDictionary), style: .MailingAddress)
}
于 2015-12-18T13:22:08.250 回答
13
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    // get the address
    if let location = locations.last {
        CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (result: [CLPlacemark]?, err: NSError?) -> Void in
            if let placemark = result?.last
                , addrList = placemark.addressDictionary?["FormattedAddressLines"] as? [String]
            {
                let address =  addrList.joinWithSeparator(", ")
                print(address)
            }
        })
    }
}

以上是快速版本。

于 2015-03-29T10:21:08.137 回答
4

我正在使用 Swift 3 / XCode 8

ZYiOS 的回答很好很简短,但没有为我编译。

该问题询问如何从现有的地址字典中获取字符串地址。这就是我所做的:

import CoreLocation

func getAddressString(placemark: CLPlacemark) -> String? {
    var originAddress : String?

    if let addrList = placemark.addressDictionary?["FormattedAddressLines"] as? [String]
    {
        originAddress =  addrList.joined(separator: ", ")
    }

    return originAddress
}
于 2016-10-04T21:12:26.990 回答
2

Swift 3 / Xcode 8 Helper Mehtod 从 CLPlaceMark 获取地址

class func formattedAddress(fromPlacemark placemark: CLPlacemark) -> String{
    var address = ""

    if let name = placemark.addressDictionary?["Name"] as? String {
        address = constructAddressString(address, newString: name)
    }

    if let city = placemark.addressDictionary?["City"] as? String {
        address = constructAddressString(address, newString: city)
    }

    if let state = placemark.addressDictionary?["State"] as? String {
        address = constructAddressString(address, newString: state)
    }

    if let country = placemark.country{
      address = constructAddressString(address, newString: country)
    }

    return address
  }
于 2016-10-28T11:52:43.060 回答
1

现在这很简单

func updateUserAddress(coordinates: CLLocationCoordinate2D) {
    let geoCoder = CLGeocoder()
    let location = CLLocation(latitude: coordinates.latitude, longitude: coordinates.longitude)
    geoCoder.reverseGeocodeLocation(location) {[weak self] (placemarks, error) in
        if error == nil, let placemark = placemarks?.first, let address = placemark.postalAddress {
            self?.userLocationLabel.text = CNPostalAddressFormatter.string(from: address, style: .mailingAddress)
        }
    }
}
于 2020-07-17T08:13:12.193 回答
1

iOS 11+

import CoreLocation
import Contacts

public extension CLPlacemark {
    func formattedAddress() -> String? {
        guard let postalAddress = postalAddress else { return nil }
        let formatter = CNPostalAddressFormatter()
        formatter.style = .mailingAddress
        let formatterString = formatter.string(from: postalAddress)
        return formatterString.replacingOccurrences(of: "\n", with: " ")
    }
}
于 2021-05-08T03:22:30.833 回答
0

只需为以下内容创建扩展名CLLocation

typealias AddressDictionaryHandler = ([String: Any]?) -> Void

extension CLLocation {

    func addressDictionary(completion: @escaping AddressDictionaryHandler) {

        CLGeocoder().reverseGeocodeLocation(self) { placemarks, _ in
            completion(placemarks?.first?.addressDictionary as? [String: AnyObject])
        }
    }
}

例子:

let location = CLLocation()

location.addressDictionary { dictionary in

    let city = dictionary?["City"] as? String
    let street = dictionary?["Street"] as? String
}
于 2017-05-10T09:51:02.990 回答
0

斯威夫特 5 版本

CLGeocoder().reverseGeocodeLocation(newLocation!, preferredLocale: nil) { (clPlacemark: [CLPlacemark]?, error: Error?) in
            guard let place = clPlacemark?.first else {
                print("No placemark from Apple: \(String(describing: error))")
                return
            }

            if let addrList = place.addressDictionary?["FormattedAddressLines"] as? [String] {
                let addressString = addrList.joined(separator: ", ")
                print(addressString)

            }
        }
于 2019-12-19T10:32:56.370 回答