Mos*_*fat 24 geocoding objective-c ios swift
我想格式化CLPlacemark为字符串.
众所周知的方法是使用,ABCreateStringWithAddressDictionary但它在iOS 9中已被弃用.警告告诉我使用CNPostalAddressFormatter.
但是,CNPostalAddressFormatter只能格式化CNPostalAddress.没有办法正确转换CLPlacemark为CNPostalAddress; 仅这3个性质通过共享CLPlacemark和CNPostalAddress:country,ISOcountryCode,和postalCode.
那么我应该如何格式化CLPlacemark为现在的字符串?
mat*_*att 26
取地标addressDictionary并使用其"FormattedAddressLines"密钥提取地址字符串.请注意,这是字符串行的数组.
(但是,你是正确的,那些负责转换到Contacts框架的Apple开发人员似乎完全忘记了Address Book和CLPlacemark之间的交换.这是Contacts框架中的一个严重错误 - 很多人中的一个.)
编辑因为我最初发布了这个答案,Apple修复了这个错误.CLPlacemark现在有一个postalAddress属性是CNPostalAddress,然后您可以使用CNPostalAddressFormatter来获取一个漂亮的多行地址字符串.一定要import Contacts!
gui*_*ido 14
if let lines = myCLPlacemark.addressDictionary?["FormattedAddressLines"] as? [String] {
let placeString = lines.joined(separator: ", ")
// Do your thing
}
Run Code Online (Sandbox Code Playgroud)
extension String {
init?(placemark: CLPlacemark?) {
// Yadda, yadda, yadda
}
}
Run Code Online (Sandbox Code Playgroud)
我第一次去移植AddressDictionary方法,就像其他海报一样.但这意味着失去了CNPostalAddress类和格式化程序的功能和灵活性.因此,方法2.
extension String {
// original method (edited)
init?(depreciated placemark1: CLPlacemark?) {
// UPDATE: **addressDictionary depreciated in iOS 11**
guard
let myAddressDictionary = placemark1?.addressDictionary,
let myAddressLines = myAddressDictionary["FormattedAddressLines"] as? [String]
else { return nil }
self.init(myAddressLines.joined(separator: " "))
}
// my preferred method - let CNPostalAddressFormatter do the heavy lifting
init?(betterMethod placemark2: CLPlacemark?) {
// where the magic is:
guard let postalAddress = CNMutablePostalAddress(placemark: placemark2) else { return nil }
self.init(CNPostalAddressFormatter().string(from: postalAddress))
}
}
Run Code Online (Sandbox Code Playgroud)
等等,那是什么CLPlacemark→ CNPostalAddress初始化器?
extension CNMutablePostalAddress {
convenience init(placemark: CLPlacemark) {
self.init()
street = [placemark.subThoroughfare, placemark.thoroughfare]
.compactMap { $0 } // remove nils, so that...
.joined(separator: " ") // ...only if both != nil, add a space.
/*
// Equivalent street assignment, w/o flatMap + joined:
if let subThoroughfare = placemark.subThoroughfare,
let thoroughfare = placemark.thoroughfare {
street = "\(subThoroughfare) \(thoroughfare)"
} else {
street = (placemark.subThoroughfare ?? "") + (placemark.thoroughfare ?? "")
}
*/
city = placemark.locality ?? ""
state = placemark.administrativeArea ?? ""
postalCode = placemark.postalCode ?? ""
country = placemark.country ?? ""
isoCountryCode = placemark.isoCountryCode ?? ""
if #available(iOS 10.3, *) {
subLocality = placemark.subLocality ?? ""
subAdministrativeArea = placemark.subAdministrativeArea ?? ""
}
}
}
Run Code Online (Sandbox Code Playgroud)
func quickAndDirtyDemo() {
let location = CLLocation(latitude: 38.8977, longitude: -77.0365)
CLGeocoder().reverseGeocodeLocation(location) { (placemarks, _) in
if let address = String(depreciated: placemarks?.first) {
print("\nAddress Dictionary method:\n\(address)") }
if let address = String(betterMethod: placemarks?.first) {
print("\nEnumerated init method:\n\(address)") }
}
}
/* Output:
Address Dictionary method:
The White House 1600 Pennsylvania Ave NW Washington, DC 20500 United States
Enumerated init method:
1600 Pennsylvania Ave NW
Washington DC 20500
United States
*/
Run Code Online (Sandbox Code Playgroud)
在这里读到的人都会得到一件免费的T恤.(并不是的)
*此代码适用于Swift 3和4,除了flatMap删除nil值已compactMap在Swift 4.1中折旧/重命名(Doc 此处,或参见SE-187的基本原理).
| 归档时间: |
|
| 查看次数: |
6850 次 |
| 最近记录: |