Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Address String from CLPlacemark

Can anyone suggest a cleaner was to create a address string from a CLPlacemark.

At present I am using this extension

extension CLPlacemark {

    func makeAddressString() -> String {
        var address = ""
        if subThoroughfare != nil { address = address + " " + subThoroughfare! }
        if thoroughfare != nil { address = address + " " + thoroughfare! }
        if locality != nil { address = address + " " + locality! }
        if administrativeArea != nil { address = address + " " + administrativeArea! }
        if postalCode != nil { address = address + " " + postalCode! }
        if country != nil { address = address + " " + country! }
        return address
    }
}

All the instance variables are optionals hence the checking for nil, and I want in the same order of street number, to street, etc.

like image 301
DogCoffee Avatar asked Sep 03 '25 09:09

DogCoffee


2 Answers

CLPlacemark has a postalAddress property of type CNPostalAddress. You can format that into a locale-aware string using the CNPostalAddressFormatter.

let formatter = CNPostalAddressFormatter()
let addressString = formatter.string(from: placemark.postalAddress)
like image 197
alekop Avatar answered Sep 04 '25 22:09

alekop


You can now flatMap on an Array of Optionals in order to filter out nil values (I think this works since Swift 2). Your example is now basically a one-liner (if you delete the line breaks I inserted for readability):

extension CLPlacemark {

    func makeAddressString() -> String {
        return [subThoroughfare, thoroughfare, locality, administrativeArea, postalCode, country]
            .flatMap({ $0 })
            .joined(separator: " ")
    }
}

You can take this further, and use nested arrays to achieve more complex styles. Here is an example of a German style shortened address (MyStreet 1, 1030 City):

extension CLPlacemark {

    var customAddress: String {
        get {
            return [[thoroughfare, subThoroughfare], [postalCode, locality]]
                .map { (subComponents) -> String in
                    // Combine subcomponents with spaces (e.g. 1030 + City),
                    subComponents.flatMap({ $0 }).joined(separator: " ")
                }
                .filter({ return !$0.isEmpty }) // e.g. no street available
                .joined(separator: ", ") // e.g. "MyStreet 1" + ", " + "1030 City"
        }
    }
}
like image 39
manmal Avatar answered Sep 04 '25 23:09

manmal