How to get formatted address NSString from AddressDictionary?
After doing some digging under iOS 6.1 I found out that the CLPlacemark address dictionary contains a pre-formatted address:
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);
}];
I couldn't yet find documentation about this, but it works for all the addresses that I tested.
The documentation for the addressDictionary
property says:
You can format the contents of this dictionary to get a full address string as opposed to building the address yourself. To format the dictionary, use the ABCreateStringWithAddressDictionary function as described in Address Book UI Functions Reference.
So add and import the AddressBookUI
framework and try:
subtitle =
ABCreateStringWithAddressDictionary(placemark.addressDictionary, NO);
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)
}
})
}
}
Above is the swift version.
As highlighted by Martyn Davis, ABCreateStringWithAddressDictionary
is deprecated in iOS 9.
You can use the functions below to convert the addressDictionary
to the newer CNMutablePostalAddress
, then use the CNPostalAddressFormatter
to generate a localised string as long as you import the Contacts
framework.
Swift 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)
}
Swift 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)
}