从CLPlacemark创建地址字符串

4

有人能否建议一种更简洁的方法来从CLPlacemark创建地址字符串。

目前,我正在使用以下扩展:

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

所有实例变量都是可选的,因此需要检查是否为nil,并且我希望以相同的顺序显示街道号码、街道等。


如果您认为我的回答解决了您的问题,请考虑将其标记为已接受。 - manmal
4个回答

10

CLPlacemark 有一个类型为 CNPostalAddresspostalAddress 属性。您可以使用 CNPostalAddressFormatter 将其格式化为 与本地化相关的 字符串。

let formatter = CNPostalAddressFormatter()
let addressString = formatter.string(from: placemark.postalAddress)

5

现在你可以对Optional的数组进行flatMap操作,以过滤掉nil值(我认为这个功能从Swift 2开始就存在了)。现在你的示例代码基本上只需要一行代码就可以实现(如果你删除我为了可读性插入的换行符):

extension CLPlacemark {

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

您可以进一步使用嵌套数组来实现更复杂的样式。这里是一个德国风格的缩短地址示例(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"
        }
    }
}

0
由于某种原因,无论是使用`CNPostalAddressFormatter()`函数还是遍历属性(如`thoroughfare`),都无法帮助我:返回的地址不是“完整”的,即缺少一些像“省份”(在那些有这种概念的国家)的东西。
因此,我不得不想出一个有点技巧性但有效的(对于我的用例而言)解决方法:
extension CLPlacemark {

    func address() -> String {
        var address: String = description.components(separatedBy: "@").first ?? description
        address.trimPrefix("\(name ?? ""), ")
        return address
    }

}

基本上,我提取包含我需要的所有细节(包括"省份"之类的内容)的description,然后删除我不需要的所有细节(它们在@之后出现,所以我将其作为分隔符进行分割)。
我知道如果苹果改变了生成description的方式,可能会出现错误,但到目前为止,它运行得非常顺利。

-1

这个也应该可以工作。

extension CLPlacemark {

  func makeAddressString() -> String {
    // Unwrapping the optionals using switch statement
    switch (self.subThoroughfare, self.thoroughfare, self.locality, self.administrativeArea, self.postalCode, self.country) {
    case let (.Some(subThoroughfare), .Some(thoroughfare), .Some(locality), .Some(administrativeArea), .Some(postalCode), .Some(country)):
        return "\(subThoroughfare), \(thoroughfare), \(locality), \(administrativeArea), \(postalCode), \(country)"
    default:
        return ""
    }
  }
}

请参考以下文章: http://natashatherobot.com/swift-unwrap-multiple-optionals/

编辑 - 仅当所有可选项都不为nil时,此方法才有效。如果其中一个为nil,则无法匹配。请查看参考链接,了解如何检测可能为nil的情况。


1
我认为这样做不行,即使其中一个或两个是nil,我仍然需要将剩余的部分组合成字符串。 - DogCoffee

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