Get country code from country name in IOS
Asked Answered
C

9

25

Im retrieving a country name from a server in english. For example, "Spain"

What I want to do is, assuming the country name is going to be written in english, get the country code.

What should I do? I´ve found getting the country name from the country code quite easy, but I´ve got no idea of how to do the opposite operation.

Thanks a lot.

Can answered 1/10, 2012 at 10:48 Comment(3)
How are you getting the code from the country name? Just do the opposite :)Pelaga
I hope this linke will help you #503264Broadwater
Ive already checked it, but what i want is to get just one CountryCode according to a country name, not a list of countriesCan
S
30

Jef's answer helped here, with slight additions.

NSArray *countryCodes = [NSLocale ISOCountryCodes];
NSMutableArray *countries = [NSMutableArray arrayWithCapacity:[countryCodes count]];

for (NSString *countryCode in countryCodes)
{
    NSString *identifier = [NSLocale localeIdentifierFromComponents: [NSDictionary dictionaryWithObject: countryCode forKey: NSLocaleCountryCode]];
    NSString *country = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_UK"] displayNameForKey: NSLocaleIdentifier value: identifier];
    [countries addObject: country];
}

NSDictionary *codeForCountryDictionary = [[NSDictionary alloc] initWithObjects:countryCodes forKeys:countries];

Now go through the 'codeForCountryDictionary' with the name of the country for which you require the code, for example,

NSLog(@"%@",[codeForCountryDictionary objectForKey:@"Spain"]);

would yield the result as 'ES', which is the 2 letter country code for spain.

Shuma answered 30/11, 2012 at 9:39 Comment(3)
Well, if you know the country names are in English, you should of course NOT use the currentLocale, but a fixed locale. The currentLocale can be in any language. Use [NSLocale initWithLocaleIdentifier:@"en_UK"] instead.Angioma
initWithLocaleIdentifier is an instance method, not a class method, so use [[NSLocale alloc] initWithLocaleIdentifier:@"en_UK"] insteadClayberg
Just to make sure I would also lower/upper case the dictionary keys. We're not sure what the server returns (which is a different problem, but at least that can minimize the 'displayName' weakness)Hong
F
16

A Swift 4 updated version of @Daxesh Nagar solution:

private func locale(for fullCountryName : String) -> String {
    var locales : String = ""
    for localeCode in NSLocale.isoCountryCodes {
        let identifier = NSLocale(localeIdentifier: localeCode)
        let countryName = identifier.displayName(forKey: NSLocale.Key.countryCode, value: localeCode)
        if fullCountryName.lowercased() == countryName?.lowercased() {
            return localeCode as! String
        }
    }
    return locales
}

For this Input as fullCountryName

"United Kingdom"

It will return the country code as follows

"GB"

Hope it helps you guys!

Fabliau answered 14/2, 2018 at 15:28 Comment(3)
This only seems to work if you're in an English speaking locale, right? Any suggestions on if the fullCountryName was "Estados Unidos"? Nice solution, thanks!Teirtza
I'd suggest a better name for this function. This doesn't return a locale, it returns a country code.Schematism
Please note that this code only works if the country name is in the appropriate language of the country code. For example, "Spain" gives nothing but "España" returns "ES".Schematism
M
4

In the Swift you will use this code

extension NSLocale {
    class func locales1(countryName1 : String) -> String {
        var locales : String = ""
        for localeCode in NSLocale.ISOCountryCodes() {
            let countryName = NSLocale.systemLocale().displayNameForKey(NSLocaleCountryCode, value: localeCode)!
            if countryName1.lowercaseString == countryName.lowercaseString {
                return localeCode as! String
            }
        }
        return locales
    }


}

Get the data:

strP2countrycode = NSLocale.locales1("PASS_COUNTRYNAME")
Mazonson answered 19/8, 2015 at 10:59 Comment(0)
S
3

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`
Schematism answered 21/5, 2019 at 19:25 Comment(0)
S
2

My compact version including the fix for matching only against english country names version.

extension NSLocale
{
    class func localeForCountry(countryName : String) -> String?
    {
        return NSLocale.ISOCountryCodes().first{self.countryNameFromLocaleCode($0 as! String) == countryName} as? String
    }

    private class func countryNameFromLocaleCode(localeCode : String) -> String
    {
        return NSLocale(localeIdentifier: "en_UK").displayNameForKey(NSLocaleCountryCode, value: localeCode) ?? ""
    }
}
Supercargo answered 9/9, 2015 at 0:11 Comment(1)
I would suggest using the special locale of en_US_POSIX when you want to ensure standard English names and formatting.Schematism
B
2

Using swift 3 (some of the answers above are missing a piece)

extension NSLocale {
class func locales1(countryName1 : String) -> String {
    let locales : String = ""
    for localeCode in NSLocale.isoCountryCodes {
        let countryName = (Locale.current as NSLocale).displayName(forKey: .countryCode, value: localeCode)
        if countryName1.lowercased() == countryName?.lowercased() {
            return localeCode
        }
    }
    return locales
}
}
Bromal answered 10/2, 2017 at 17:2 Comment(1)
Why create an extension to NSLocale instead of Locale in Swift 3?Schematism
S
1

Swift 3.0 :

Getting the country code and country name as NS Dictionary-

let countryCodes: [AnyObject] = NSLocale.isoCountryCodes as [AnyObject]

        let countries: NSMutableArray = NSMutableArray(capacity: countryCodes.count)

        for countryCode in countryCodes {
            let identifier: String = NSLocale.localeIdentifier(fromComponents: NSDictionary(object: countryCode, forKey: NSLocale.Key.countryCode as NSCopying) as! [String : String])
            let country: String = NSLocale(localeIdentifier: "en_US").displayName(forKey: NSLocale.Key.identifier, value: identifier)!
            countries.add(country)
        }
        let codeForCountryDictionary: [NSObject : AnyObject] = NSDictionary(objects: countryCodes, forKeys: countries as! [NSCopying]) as [NSObject : AnyObject]

        print(codeForCountryDictionary)
Shemikashemite answered 14/7, 2017 at 11:24 Comment(1)
Why all of the NS classes in Swift 3?Schematism
A
0

So this solution works well in swift 4 taken from comments above...

extension NSLocale {
   struct Locale {
    let countryCode: String
    let countryName: String
   }

  class func locales() -> [Locale] {

    var locales = [Locale]()

    for localeCode in NSLocale.isoCountryCodes {
        let identifier = NSLocale(localeIdentifier: localeCode)
        let countryName = identifier.displayName(forKey: NSLocale.Key.countryCode, value: localeCode)!
        let countryCode = localeCode
        let locale = Locale(countryCode: countryCode, countryName: countryName)
        locales.append(locale)
    }

    return locales.sorted{$0.countryName.localizedCaseInsensitiveCompare($1.countryName) == ComparisonResult.orderedAscending}
 }
}

enjoy!

Agha answered 15/2, 2018 at 21:32 Comment(1)
This makes no attempt to answer the question. And you certainly should not be naming a struct Locale in Swift since Locale is already a struct provided by Foundation.Schematism
M
-1

Swift 5

extension Locale {
    func countryCode(by countryName: String) -> String? {
        return Locale.isoRegionCodes.first(where: { code -> Bool in
            guard let localizedCountryName = localizedString(forRegionCode: code) else {
                return false
            }
            return localizedCountryName.lowercased() == countryName.lowercased()
        })
    }
}

To use:

let locale = Locale(identifier: "en_US")
let countryCode = locale.countryCode(by: "Russia")
Mallory answered 17/1, 2021 at 8:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.