Создать строку адреса из CLPlacemark
Может кто-нибудь предложить уборщику было создать адресную строку из 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
}
}
Все переменные экземпляра являются опциональными, следовательно, проверка на ноль, и я хочу в том же порядке номера улицы, улицы и т. Д.
4 ответа
CLPlacemark
имеет postalAddress
свойство типа CNPostalAddress
, Вы можете отформатировать его в строку с указанием локали, используя CNPostalAddressFormatter
,
let formatter = CNPostalAddressFormatter()
let addressString = formatter.string(from: placemark.postalAddress)
Теперь вы можете использовать FlatMap для Array of Optionals, чтобы отфильтровать 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"
}
}
}
Почему-то ниCNPostalAddressFormatter()
, а также не перебирать такие свойства, какthoroughfare
мне помогло: возвращаемые адреса были не "полными", т.е. в них отсутствовали такие вещи, как "провинция" (в тех странах, где есть такое понятие).
Итак, мне пришлось придумать немного хакиш, но работающий (для моего случая) обходной путь:
extension CLPlacemark {
func address() -> String {
var address: String = description.components(separatedBy: "@").first ?? description
address.trimPrefix("\(name ?? ""), ")
return address
}
}
По сути, я беру файл , который содержит все необходимые мне сведения (включая такие вещи, как «провинция»), и удаляю все ненужные сведения (они идут после@
, поэтому я использую его как разделитель для разделения).
Я знаю, что если Apple изменит подход, могут возникнуть ошибки.description
генерируется, но пока работает безупречно.
Это должно работать тоже.
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/
РЕДАКТИРОВАТЬ - Это будет работать, только если ни один из дополнительных опций не равен нулю, если один из них равен нулю, регистр не будет совпадать. Проверьте ссылку ссылки, чтобы увидеть, как вы можете обнаружить случаи, когда один может быть ноль.