Как локализовать международный адрес, в особенности проезд и субооборот - PullRequest
0 голосов
/ 31 марта 2020

Я работаю над приложением, которое интенсивно использует адреса в разных странах. У нас есть несколько способов ввода их от импортируемых адресов до сбрасывания булавок на карте, для обратного геокодирования нашего текущего местоположения.

Мой текущий проект заключается в правильном форматировании международного адреса:

In США:

18 Street Name

В Норвегии:

Street Name 18

Я нашел несколько способов создания экземпляров CNMutablePostalAddress с CLPlacemark, чтобы получить довольно хорошие результаты, проблема, с которой я столкнулся, заключается в следующем.

Я хочу, чтобы только название улицы и номер возвращались в виде одной строки: Итак: 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, были бы полезны.

1 Ответ

0 голосов
/ 01 апреля 2020

В итоге я выбрал гибридный подход.

Для CLPlacemark до CNMutablePostalAddress() это довольно прямо вперед:

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