Here is a simple solution that works in Swift 3 or later. Depending on your OS version, this supports roughly 256 country names and codes.
iOS 16+
extension Locale {
func isoCode(for countryName: String) -> String? {
Locale.Region.isoRegions.first { region -> Bool in
localizedString(forRegionCode: region.identifier)?.compare(countryName, options: [.caseInsensitive, .diacriticInsensitive]) == .orderedSame
}?.identifier
}
}
iOS 15-
extension Locale {
func isoCode(for countryName: String) -> String? {
return Locale.isoRegionCodes.first(where: { (code) -> Bool in
localizedString(forRegionCode: code)?.compare(countryName, options: [.caseInsensitive, .diacriticInsensitive]) == .orderedSame
})
}
}
The trick to using this correctly is knowing the language of the country names you wish to convert to the standard 2-letter ISO country code.
If you know the country names are in English, you must use this on a locale set to English. It would be best to use the special locale of en_US_POSIX
in such a case.
let locale = Locale(identifier: "en_US_POSIX")
print(locale.isoCode(for: "Spain")) // result is `ES`
If you have country names in Spanish, then be sure to use a Spanish locale:
let locale = Locale(identifier: "es")
print(locale.isoCode(for: "España")) // result is `ES`