我正在开发一个大量使用不同国家地址的应用程序。我们有很多方法来输入它们,从导入地址,到在地图上放置大头针,以反向地理编码我们当前的位置。
我目前的项目是正确格式化国际地址:
在美国:
18 Street Name
在挪威:
Street Name 18
我已经想出了一堆用CLPlacemark实例化CNMutablePostalAddress的方法,以获得一些很好的结果,我遇到的问题是这样的。
我只想以一行字符串的形式返回街道名称和数字: So:street1: placemarker.thoroughfare, (street name) street2: placemarker.subThoroughfare (street number),
但是CNPostalAddress只有一个street属性,所以要使用它,你需要这样做:
cNPostalAddress.street = placemarker.subThoroughfare + " " + placemarker.thoroughfare
这对挪威这样备受推崇的国家是行不通的。
您可以修改它,并使用从格式化地址中取出第一行:
CNPostalAddressFormatter.string(from: placemarker.mailingAddress , style: .mailingAddress)
但这是超级老生常谈的,我相信它将打破像日本这样不同的邮寄地址顺序的国家。
目前,我甚至找不到任何资源来告诉我哪些国家撤销了subThoroughfare和thoroughfare,因为如果我有一个这样的列表,我可以手动地撤销它。
以下是我到目前为止管理的一些示例代码:
static func mulitLineAddress(from placemarker: CLPlacemark, detail: AddressDetail) -> String {
let address = MailingAddress(
street1: placemarker.thoroughfare,
street2: placemarker.subThoroughfare,
city: placemarker.locality,
state: placemarker.administrativeArea,
postalCode: placemarker.postalCode,
countryCode: placemarker.country)
return self.mulitLineAddress(from: address, detail: detail)
}
static func mulitLineAddress(from mailingAddress: MailingAddress, detail: AddressDetail) -> String {
let address = CNMutablePostalAddress()
let street1 = mailingAddress.street1 ?? ""
let street2 = mailingAddress.street2 ?? ""
let streetSpacing = street1.isEmpty && street2.isEmpty ? "" : " "
let streetFull = street1 + streetSpacing + street2
switch detail {
case .street1:
address.street = street1
case .street2:
address.street = street2
case .streetFull:
address.street = streetFull
case .full:
address.country = mailingAddress.countryCode ?? ""
fallthrough
case .withoutCountry:
address.street = streetFull
address.city = mailingAddress.city ?? ""
address.state = mailingAddress.state ?? ""
address.postalCode = mailingAddress.postalCode ?? ""
}
return CNPostalAddressFormatter.string(from: address, style: .mailingAddress)
}有什么想法吗?甚至像反向street1和street2的国家列表这样的资源也是有用的。
发布于 2020-04-01 10:48:24
我最终采用了一种混合方法。
对于CNMutablePostalAddress()的CLPlacemark来说,这是非常直接的:
cnPostalAddress.street = placemarker.postalAddress?.street
但是,这不适用于任何其他输入方法,并且不能修改为与CNMutablePostalAddress()不同的格式
当我需要手动从其他来源引入地址信息时,这里有一个适用于几个国家的示例:
static private func generateLocalizedStreetAddress(from adderss: MailingAddress) -> String {
guard adderss.localizedStreet.isEmpty else { return adderss.localizedStreet ?? "" }
let country = CountryCode.country(for: adderss.countryCode)
let thoroughfare = adderss.thoroughfare ?? ""
let subThoroughfare = adderss.subThoroughfare ?? ""
let delimiter = self.generateDelimiter(from: thoroughfare, and: subThoroughfare, with: country)
switch country {
case .belgium, .czechRepublic, .denmark, .finland, .germany, .latvia, .netherlands, .norway, .poland, .portugal, .sweden:
return thoroughfare + delimiter + subThoroughfare
default:
return subThoroughfare + delimiter + thoroughfare
}
}
static private func generateDelimiter(from thoroughfare: String, and subThoroughfare: String, with country: Country) -> String {
guard !thoroughfare.isEmpty && !subThoroughfare.isEmpty else { return "" }
switch country {
case .spain:
return ", "
default:
return " "
}
}发布于 2020-09-08 04:16:39
CNPostalAddressFormatter有一个有趣的API来获取一个NSAttributedString,其中每个地址组件都是在其中标识的。您可以使用它来提取您想要的信息,比如街道,它包括适当本地化的子大道和大道,而不管它可能存在于邮政地址中的什么位置。
let addressFormatter = CNPostalAddressFormatter()
let attributedAddress = addressFormatter.attributedString(from: postalAddress, withDefaultAttributes: [:])
let nsString = attributedAddress.string as NSString
let range = NSRange(location: 0, length: nsString.length)
var street: String?
attributedAddress.enumerateAttributes(in: range, options: []) { result, range, stop in
if let component = result[NSAttributedString.Key(CNPostalAddressPropertyAttribute)] as? String {
if component == CNPostalAddressStreetKey {
street = nsString.substring(with: range)
stop.pointee = true
}
}
}我还向苹果提交了反馈,希望添加一个更强大、更灵活的应用程序接口: FB8648023模板应用程序接口,用于格式化与DateFormatter.setLocalizedDateFormatFromTemplate类似的指定组件的地址
https://stackoverflow.com/questions/60943079
复制相似问题