Ruby: Should strings in a frozen array also be individually frozen? - ruby-on-rails

Ruby 2.2.3, Rails 4.2.1
I have a large number of arrays of strings that I define as constants for use throughout an application. They are various sets of ISO country codes, language codes, that sort of thing, so two to four characters, numbered in the hundreds of unique values each.
The different arrays are collections of these, so NORTH_AMERICA_COUNTRY_CODES might be an array of a dozen of so country codes, AFRICA_COUNTRY_CODES might be an array of around 60. Many of them overlap (various versions of the Commonwealth countries, for example).
The arrays are used in comparison with other arbitrary arrays of country codes for logic such as "Subtract this list of countries from Africa".
So I'm wondering whether, when I generate these constants, I ought to freeze the strings within the arrays, so instead of:
WORLD_COUNTRIES = Countries.pluck(:country_code).freeze
... maybe ...
WORLD_COUNTRIES = Countries.pluck(:country_code).map{|c| c.freeze}.freeze
Is there a way of quantifying the potential benefits?
I considered using arrays of symbols instead of arrays of strings, but the arbitrary arrays that these are used with are stored in PostgreSQL text arrays, and it seems like I'd need to serialise those columns instead, or maybe override the getter and setter methods to change the values between arrays of strings and arrays of symbols. Ugh.
Edit
Testing results, in which I've attempted to benchmark three situations:
Comparing a frozen array of unfrozen strings with an unfrozen array of unfrozen strings
Comparing a frozen array of frozen strings with an unfrozen array of unfrozen strings
Comparing a frozen array of symbols with an unfrozen array of symbols (in case I bit the bullet and went all symbolic on this).
Any thoughts on methodology or interpretation gratefully received. I'm not sure whether the similarity in results between the first two indicates that they are in all respects the same, but I'd be keen on anything that can directly point to differences in memory allocation.
Script:
require 'benchmark'
country_list = ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"]
FROZEN_ARRAY = country_list.dup.freeze
puts FROZEN_ARRAY.size
FROZEN_ARRAY_AND_STRINGS = country_list.dup.map{|x| x.freeze}.freeze
FROZEN_ARRAY_AND_SYMBOLS = country_list.dup.map{|x| x.to_sym}.freeze
comp_s = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA)
comp_sym = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA).map{|x| x.to_sym}
Benchmark.bm do |x|
x.report("frozen string" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
x.report("unfrozen string") { 10000.times {|i| c = (FROZEN_ARRAY & comp_s.dup) }}
x.report("symbols" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
end
Benchmark.bmbm do |x|
x.report("frozen string" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
x.report("unfrozen string") { 10000.times {|i| c = (FROZEN_ARRAY & comp_s.dup) }}
x.report("symbols" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
end
Result:
2.2.3 :001 > require 'benchmark'
=> false
2.2.3 :002 >
2.2.3 :003 > country_list = ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"]
=> ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"]
2.2.3 :004 > FROZEN_ARRAY = country_list.dup.freeze
=> ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"]
2.2.3 :005 > puts FROZEN_ARRAY.size
252
=> nil
2.2.3 :006 > FROZEN_ARRAY_AND_STRINGS = country_list.dup.map{|x| x.freeze}.freeze
=> ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZW"]
2.2.3 :007 > FROZEN_ARRAY_AND_SYMBOLS = country_list.dup.map{|x| x.to_sym}.freeze
=> [:AD, :AE, :AF, :AG, :AI, :AL, :AM, :AN, :AO, :AQ, :AR, :AS, :AT, :AU, :AW, :AX, :AZ, :BA, :BB, :BD, :BE, :BF, :BG, :BH, :BI, :BJ, :BL, :BM, :BN, :BO, :BQ, :BR, :BS, :BT, :BV, :BW, :BY, :BZ, :CA, :CC, :CD, :CF, :CG, :CH, :CI, :CK, :CL, :CM, :CN, :CO, :CR, :CS, :CU, :CV, :CW, :CX, :CY, :CZ, :DE, :DJ, :DK, :DM, :DO, :DZ, :EC, :EE, :EG, :EH, :ER, :ES, :ET, :FI, :FJ, :FK, :FM, :FO, :FR, :GA, :GB, :GD, :GE, :GF, :GG, :GH, :GI, :GL, :GM, :GN, :GP, :GQ, :GR, :GS, :GT, :GU, :GW, :GY, :HK, :HM, :HN, :HR, :HT, :HU, :ID, :IE, :IL, :IM, :IN, :IO, :IQ, :IR, :IS, :IT, :JE, :JM, :JO, :JP, :KE, :KG, :KH, :KI, :KM, :KN, :KP, :KR, :KW, :KY, :KZ, :LA, :LB, :LC, :LI, :LK, :LR, :LS, :LT, :LU, :LV, :LY, :MA, :MC, :MD, :ME, :MF, :MG, :MH, :MK, :ML, :MM, :MN, :MO, :MP, :MQ, :MR, :MS, :MT, :MU, :MV, :MW, :MX, :MY, :MZ, :NA, :NC, :NE, :NF, :NG, :NI, :NL, :NO, :NP, :NR, :NU, :NZ, :OM, :PA, :PE, :PF, :PG, :PH, :PK, :PL, :PM, :PN, :PR, :PS, :PT, :PW, :PY, :QA, :RE, :RO, :RS, :RU, :RW, :SA, :SB, :SC, :SD, :SE, :SG, :SH, :SI, :SJ, :SK, :SL, :SM, :SN, :SO, :SR, :SS, :ST, :SV, :SX, :SY, :SZ, :TC, :TD, :TF, :TG, :TH, :TJ, :TK, :TL, :TM, :TN, :TO, :TR, :TT, :TV, :TW, :TZ, :UA, :UG, :UM, :US, :UY, :UZ, :VA, :VC, :VE, :VG, :VI, :VN, :VU, :WF, :WS, :YE, :YT, :YU, :ZA, :ZM, :ZW]
2.2.3 :008 > comp_s = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA)
=> ["AD", "AT", "BE", "CY", "EE", "FI", "FR", "DE", "ES", "GR", "IE", "IT", "LU", "LV", "MC", "ME", "MT", "NL", "PT", "SI", "SK", "SM", "VA"]
2.2.3 :009 > comp_sym = %w(AD AT BE CY EE FI FR DE ES GR IE IT LU LV MC ME MT NL PT SI SK SM VA).map{|x| x.to_sym}
=> [:AD, :AT, :BE, :CY, :EE, :FI, :FR, :DE, :ES, :GR, :IE, :IT, :LU, :LV, :MC, :ME, :MT, :NL, :PT, :SI, :SK, :SM, :VA]
2.2.3 :010 >
2.2.3 :011 >
2.2.3 :012 > Benchmark.bm do |x|
2.2.3 :013 > x.report("frozen string" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
2.2.3 :014?> x.report("unfrozen string") { 10000.times {|i| c = (FROZEN_ARRAY & comp_s.dup) }}
2.2.3 :015?> x.report("symbols" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
2.2.3 :016?> end
user system total real
frozen string 0.190000 0.000000 0.190000 ( 0.194141)
unfrozen string 0.170000 0.010000 0.180000 ( 0.174675)
symbols 0.080000 0.000000 0.080000 ( 0.081507)
=> [#<Benchmark::Tms:0x007f810c3aca70 #label="frozen string", #real=0.1941408810671419, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.1899999999999995, #total=0.1899999999999995>, #<Benchmark::Tms:0x007f810c82b538 #label="unfrozen string", #real=0.1746752569451928, #cstime=0.0, #cutime=0.0, #stime=0.010000000000000009, #utime=0.16999999999999993, #total=0.17999999999999994>, #<Benchmark::Tms:0x007f810af2cfa0 #label="symbols", #real=0.08150708093307912, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.08000000000000007, #total=0.08000000000000007>]
2.2.3 :017 >
2.2.3 :018 >
2.2.3 :019 > Benchmark.bmbm do |x|
2.2.3 :020 > x.report("frozen string" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_STRINGS & comp_s.dup) }}
2.2.3 :021?> x.report("unfrozen string") { 10000.times {|i| c = (FROZEN_ARRAY & comp_s.dup) }}
2.2.3 :022?> x.report("symbols" ) { 10000.times {|i| c = (FROZEN_ARRAY_AND_SYMBOLS & comp_sym.dup) }}
2.2.3 :023?> end
Rehearsal ---------------------------------------------------
frozen string 0.180000 0.000000 0.180000 ( 0.183846)
unfrozen string 0.200000 0.000000 0.200000 ( 0.196311)
symbols 0.080000 0.000000 0.080000 ( 0.082794)
------------------------------------------ total: 0.460000sec
user system total real
frozen string 0.160000 0.000000 0.160000 ( 0.167051)
unfrozen string 0.170000 0.000000 0.170000 ( 0.171601)
symbols 0.080000 0.000000 0.080000 ( 0.078746)
=> [#<Benchmark::Tms:0x007f811022a388 #label="frozen string", #real=0.1670510449912399, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.16000000000000014, #total=0.16000000000000014>, #<Benchmark::Tms:0x007f811022a4c8 #label="unfrozen string", #real=0.17160122003406286, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.16999999999999993, #total=0.16999999999999993>, #<Benchmark::Tms:0x007f8108eb1c58 #label="symbols", #real=0.07874645793344826, #cstime=0.0, #cutime=0.0, #stime=0.0, #utime=0.08000000000000007, #total=0.08000000000000007>]
2.2.3 :024 >
2.2.3 :025 >
2.2.3 :026 >

Since you're dealing with a small number of values, and since the performance benefits of symbols are evident from your testing, just go with symbols.
BTW, you can use map(&:to_sym) instead of map {|x| x.to_sym}.

Related

Creating a Data Model for nested JSON parameters

I am working with the Spotify API and having trouble with the data model due to the JSON data being more complex than any other data I've seen via tutorials or courses. How would I make my struct for the "items" in this JSON data? I understand a majority of the parameters, for example, "album_group": String and "available_markets": [String] but I don't understand what to do with "artists", "external_urls", and "images". Any help would be appreciated.
Below is the first "item" from the data.
Side Note When I'm creating my struct do I have to include EVERY parameter shown below for my API call to work?
{
"href": "https://api.spotify.com/v1/artists/3qiHUAX7zY4Qnjx8TNUzVx/albums?offset=0&limit=20&include_groups=album,single,compilation,appears_on&locale=en-US,en;q=0.9",
"items": [
{
"album_group": "album",
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/3qiHUAX7zY4Qnjx8TNUzVx"
},
"href": "https://api.spotify.com/v1/artists/3qiHUAX7zY4Qnjx8TNUzVx",
"id": "3qiHUAX7zY4Qnjx8TNUzVx",
"name": "Yeat",
"type": "artist",
"uri": "spotify:artist:3qiHUAX7zY4Qnjx8TNUzVx"
}
],
"available_markets": [
"AD",
"AE",
"AG",
"AL",
"AM",
"AO",
"AR",
"AT",
"AU",
"AZ",
"BA",
"BB",
"BD",
"BE",
"BF",
"BG",
"BH",
"BI",
"BJ",
"BN",
"BO",
"BR",
"BS",
"BT",
"BW",
"BY",
"BZ",
"CA",
"CD",
"CG",
"CH",
"CI",
"CL",
"CM",
"CO",
"CR",
"CV",
"CY",
"CZ",
"DE",
"DJ",
"DK",
"DM",
"DO",
"DZ",
"EC",
"EE",
"EG",
"ES",
"FI",
"FJ",
"FM",
"FR",
"GA",
"GB",
"GD",
"GE",
"GH",
"GM",
"GN",
"GQ",
"GR",
"GT",
"GW",
"GY",
"HK",
"HN",
"HR",
"HT",
"HU",
"ID",
"IE",
"IL",
"IN",
"IQ",
"IS",
"IT",
"JM",
"JO",
"JP",
"KE",
"KG",
"KH",
"KI",
"KM",
"KN",
"KR",
"KW",
"KZ",
"LA",
"LB",
"LC",
"LI",
"LK",
"LR",
"LS",
"LT",
"LU",
"LV",
"LY",
"MA",
"MC",
"MD",
"ME",
"MG",
"MH",
"MK",
"ML",
"MN",
"MO",
"MR",
"MT",
"MU",
"MV",
"MW",
"MX",
"MY",
"MZ",
"NA",
"NE",
"NG",
"NI",
"NL",
"NO",
"NP",
"NR",
"NZ",
"OM",
"PA",
"PE",
"PG",
"PH",
"PK",
"PL",
"PS",
"PT",
"PW",
"PY",
"QA",
"RO",
"RS",
"RU",
"RW",
"SA",
"SB",
"SC",
"SE",
"SG",
"SI",
"SK",
"SL",
"SM",
"SN",
"SR",
"ST",
"SV",
"SZ",
"TD",
"TG",
"TH",
"TJ",
"TL",
"TN",
"TO",
"TR",
"TT",
"TV",
"TW",
"TZ",
"UA",
"UG",
"US",
"UY",
"UZ",
"VC",
"VE",
"VN",
"VU",
"WS",
"XK",
"ZA",
"ZM",
"ZW"
],
"external_urls": {
"spotify": "https://open.spotify.com/album/1x55Z0fYARLdeJVjG2UESs"
},
"href": "https://api.spotify.com/v1/albums/1x55Z0fYARLdeJVjG2UESs",
"id": "1x55Z0fYARLdeJVjG2UESs",
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/ab67616d0000b273b20fdc3ee4c262693cfdf005",
"width": 640
},
{
"height": 300,
"url": "https://i.scdn.co/image/ab67616d00001e02b20fdc3ee4c262693cfdf005",
"width": 300
},
{
"height": 64,
"url": "https://i.scdn.co/image/ab67616d00004851b20fdc3ee4c262693cfdf005",
"width": 64
}
],
"name": "Up 2 Më",
"release_date": "2021-09-10",
"release_date_precision": "day",
"total_tracks": 22,
"type": "album",
"uri": "spotify:album:1x55Z0fYARLdeJVjG2UESs"
}
]
}
Good rule of thumb is, that you need a separate Decodable object for every JSON object (marked with {}) when working with such API.
You can nest Decodable structs. Just don't forget that here, ExternalUrl has to be Decodable too, otherwise you will get an error
struct SpotifyItem: Decodable {
// ...
let artists: [Artist]
let images: [SpotifyImage]
// ...
}
struct Artist: Decodable {
let external_urls: ExternalUrl
let href: String
let id: String
// ...
}
struct ExternalUrl: Decodable {
let spotify: String
}
struct SpotifyImage: Decodable {
let url: String
let height: Int
let width: Int
}
Side Note Answer: I would advise you to do so. It seems like there are ways to decode JSON elements into swift dictionary, but it goes against the type safety that you are trying to achieve. You are parsing JSON into Decodable structs precisely because you want to know ahead of time what are you dealing with.
Don't forget you can still do optional attributes, for example you could have
struct ExternalUrl: Decodable {
let spotify: String
let instagram: String?
}
In that case, if instagram is not present, it will be set to nil. My advice would be follow this more modern and safe way of doing things. You can of course parse the entire JSON into a huge [String: Any] object, but you will have to write out everything you want to access anyway. Plus there will be a LOT of type casting and checks, which Codable does for you.

Swift -How to show a UIPickerView with multi strings per line (not components)

I'm not looking for a multiple component pickerView, I'm looking for 1 pickerView with multi strings per line.
I have a dictionary of country codes (keys) and the matching dialing codes (values).
I loop through the dictionary and use this function to get the country from the key. The country is a String.
As I loop I also use this function to get the emoji flag of each country. The emoji flag is a String.
Now that I have all 4 values for each country (the flag, country name, country code, and dialing code), how can I add the corresponding 3 of the 4 values to each line of a pickerView (the flag, country name, and dialing code). The pickerView should look like this:
I'm going to need to access the country name, country code, and dialing code (3 of the 4 values) inside the pickerView's didSelect.
let phoneNumberTextField: UITextField = {
let textField = UITextField()
return textField
}()
let pickerView = UIPickerView()
var countries = [String]()
var flags = [String]()
var arrOfCountriesWithTheirValues = [???]()
let dialingCodes = ["AF": "93", "AE": "971", "AL": "355", "AN": "599", "AS":"1", "AD": "376", "AO": "244", "AI": "1", "AG":"1", "AR": "54","AM": "374", "AW": "297", "AU":"61", "AT": "43","AZ": "994", "BS": "1", "BH":"973", "BF": "226","BI": "257", "BD": "880", "BB": "1", "BY": "375", "BE":"32","BZ": "501", "BJ": "229", "BM": "1", "BT":"975", "BA": "387", "BW": "267", "BR": "55", "BG": "359", "BO": "591", "BL": "590", "BN": "673", "CC": "61", "CD":"243","CI": "225", "KH":"855", "CM": "237", "CA": "1", "CV": "238", "KY":"345", "CF":"236", "CH": "41", "CL": "56", "CN":"86","CX": "61", "CO": "57", "KM": "269", "CG":"242", "CK": "682", "CR": "506", "CU":"53", "CY":"537","CZ": "420", "DE": "49", "DK": "45", "DJ":"253", "DM": "1", "DO": "1", "DZ": "213", "EC": "593", "EG":"20", "ER": "291", "EE":"372","ES": "34", "ET": "251", "FM": "691", "FK": "500", "FO": "298", "FJ": "679", "FI":"358", "FR": "33", "GB":"44", "GF": "594", "GA":"241", "GS": "500", "GM":"220", "GE":"995","GH":"233", "GI": "350", "GQ": "240", "GR": "30", "GG": "44", "GL": "299", "GD":"1", "GP": "590", "GU": "1", "GT": "502", "GN":"224","GW": "245", "GY": "595", "HT": "509", "HR": "385", "HN":"504", "HU": "36", "HK": "852", "IR": "98", "IM": "44", "IL": "972", "IO":"246", "IS": "354", "IN": "91", "ID":"62", "IQ":"964", "IE": "353","IT":"39", "JM":"1", "JP": "81", "JO": "962", "JE":"44", "KP": "850", "KR": "82","KZ":"77", "KE": "254", "KI": "686", "KW": "965", "KG":"996","KN":"1", "LC": "1", "LV": "371", "LB": "961", "LK":"94", "LS": "266", "LR":"231", "LI": "423", "LT": "370", "LU": "352", "LA": "856", "LY":"218", "MO": "853", "MK": "389", "MG":"261", "MW": "265", "MY": "60","MV": "960", "ML":"223", "MT": "356", "MH": "692", "MQ": "596", "MR":"222", "MU": "230", "MX": "52","MC": "377", "MN": "976", "ME": "382", "MP": "1", "MS": "1", "MA":"212", "MM": "95", "MF": "590", "MD":"373", "MZ": "258", "NA":"264", "NR":"674", "NP":"977", "NL": "31","NC": "687", "NZ":"64", "NI": "505", "NE": "227", "NG": "234", "NU":"683", "NF": "672", "NO": "47","OM": "968", "PK": "92", "PM": "508", "PW": "680", "PF": "689", "PA": "507", "PG":"675", "PY": "595", "PE": "51", "PH": "63", "PL":"48", "PN": "872","PT": "351", "PR": "1","PS": "970", "QA": "974", "RO":"40", "RE":"262", "RS": "381", "RU": "7", "RW": "250", "SM": "378", "SA":"966", "SN": "221", "SC": "248", "SL":"232","SG": "65", "SK": "421", "SI": "386", "SB":"677", "SH": "290", "SD": "249", "SR": "597","SZ": "268", "SE":"46", "SV": "503", "ST": "239","SO": "252", "SJ": "47", "SY":"963", "TW": "886", "TZ": "255", "TL": "670", "TD": "235", "TJ": "992", "TH": "66", "TG":"228", "TK": "690", "TO": "676", "TT": "1", "TN":"216","TR": "90", "TM": "993", "TC": "1", "TV":"688", "UG": "256", "UA": "380", "US": "1", "UY": "598","UZ": "998", "VA":"379", "VE":"58", "VN": "84", "VG": "1", "VI": "1","VC":"1", "VU":"678", "WS": "685", "WF": "681", "YE": "967", "YT": "262","ZA": "27" , "ZM": "260", "ZW":"263"]
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
phoneNumberTextField.delegate = self
phoneNumberTextField.inputView = pickerView
for (key, value) in dialingCodes {
if let country = countryName(countryCode: key) {
countries.append(country)
let emojiFlag = flag(country: key)
flags.append(emojiFlag)
// arrOfCountriesWithTheirValues.append(???)
}
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arrOfCountriesWithTheirValues.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arrOfCountriesWithTheirValues[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let threeValues = arrOfCountriesWithTheirValues[row]
}
func countryName(countryCode: String) -> String? {
let current = Locale(identifier: "en_US")
return current.localizedString(forRegionCode: countryCode)
}
func flag(country: String) -> String {
let base : UInt32 = 127397
var s = ""
for v in country.unicodeScalars {
s.unicodeScalars.append(UnicodeScalar(base + v.value)!)
}
return String(s)
}
Instead of titleForRow, implement viewForRow. Now you are free to put anything you like into the view shown on each row of the component.
I'm going to need to access the country name, country code, and dialing code (3 of the 4 values) inside the pickerView's didSelect.
Fine, but note that that has nothing to do with what is displayed in the picker view. The picker view is view. When you need the data for a selected row, you look in the model. You need to revise your model so that every item in the array contains all the information you need.

Get Country Code (Telephone) Using Locale In Swift [duplicate]

I am developing an iOS app in which the user enters their mobile number. How do I get their country calling code? For example, if a user is in India, then +91 should be prefixed automatically. Is there an option that adds country codes automatically?
Import Statement :
#import<CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
you can get country code for the current Carrier using CoreTelephony framework:
CTTelephonyNetworkInfo *network_Info = [CTTelephonyNetworkInfo new];
CTCarrier *carrier = network_Info.subscriberCellularProvider;
NSLog(#"country code is: %#", carrier.mobileCountryCode);
//will return the actual country code
NSLog(#"ISO country code is: %#", carrier.isoCountryCode);
Apple Docs
with the use of NSLocale you can get the country name, code etc. Take a look at below code it will help you to do so.
NSLocale *currentLocale = [NSLocale currentLocale]; // get the current locale.
NSString *countryCode = [currentLocale objectForKey:NSLocaleCountryCode]; // get country code, e.g. ES (Spain), FR (France), etc.
for a countries dialing code you can visit this reference code.
Use this simple function
func getCountryCallingCode(countryRegionCode:String)->String{
let prefixCodes = ["AF": "93", "AE": "971", "AL": "355", "AN": "599", "AS":"1", "AD": "376", "AO": "244", "AI": "1", "AG":"1", "AR": "54","AM": "374", "AW": "297", "AU":"61", "AT": "43","AZ": "994", "BS": "1", "BH":"973", "BF": "226","BI": "257", "BD": "880", "BB": "1", "BY": "375", "BE":"32","BZ": "501", "BJ": "229", "BM": "1", "BT":"975", "BA": "387", "BW": "267", "BR": "55", "BG": "359", "BO": "591", "BL": "590", "BN": "673", "CC": "61", "CD":"243","CI": "225", "KH":"855", "CM": "237", "CA": "1", "CV": "238", "KY":"345", "CF":"236", "CH": "41", "CL": "56", "CN":"86","CX": "61", "CO": "57", "KM": "269", "CG":"242", "CK": "682", "CR": "506", "CU":"53", "CY":"537","CZ": "420", "DE": "49", "DK": "45", "DJ":"253", "DM": "1", "DO": "1", "DZ": "213", "EC": "593", "EG":"20", "ER": "291", "EE":"372","ES": "34", "ET": "251", "FM": "691", "FK": "500", "FO": "298", "FJ": "679", "FI":"358", "FR": "33", "GB":"44", "GF": "594", "GA":"241", "GS": "500", "GM":"220", "GE":"995","GH":"233", "GI": "350", "GQ": "240", "GR": "30", "GG": "44", "GL": "299", "GD":"1", "GP": "590", "GU": "1", "GT": "502", "GN":"224","GW": "245", "GY": "595", "HT": "509", "HR": "385", "HN":"504", "HU": "36", "HK": "852", "IR": "98", "IM": "44", "IL": "972", "IO":"246", "IS": "354", "IN": "91", "ID":"62", "IQ":"964", "IE": "353","IT":"39", "JM":"1", "JP": "81", "JO": "962", "JE":"44", "KP": "850", "KR": "82","KZ":"77", "KE": "254", "KI": "686", "KW": "965", "KG":"996","KN":"1", "LC": "1", "LV": "371", "LB": "961", "LK":"94", "LS": "266", "LR":"231", "LI": "423", "LT": "370", "LU": "352", "LA": "856", "LY":"218", "MO": "853", "MK": "389", "MG":"261", "MW": "265", "MY": "60","MV": "960", "ML":"223", "MT": "356", "MH": "692", "MQ": "596", "MR":"222", "MU": "230", "MX": "52","MC": "377", "MN": "976", "ME": "382", "MP": "1", "MS": "1", "MA":"212", "MM": "95", "MF": "590", "MD":"373", "MZ": "258", "NA":"264", "NR":"674", "NP":"977", "NL": "31","NC": "687", "NZ":"64", "NI": "505", "NE": "227", "NG": "234", "NU":"683", "NF": "672", "NO": "47","OM": "968", "PK": "92", "PM": "508", "PW": "680", "PF": "689", "PA": "507", "PG":"675", "PY": "595", "PE": "51", "PH": "63", "PL":"48", "PN": "872","PT": "351", "PR": "1","PS": "970", "QA": "974", "RO":"40", "RE":"262", "RS": "381", "RU": "7", "RW": "250", "SM": "378", "SA":"966", "SN": "221", "SC": "248", "SL":"232","SG": "65", "SK": "421", "SI": "386", "SB":"677", "SH": "290", "SD": "249", "SR": "597","SZ": "268", "SE":"46", "SV": "503", "ST": "239","SO": "252", "SJ": "47", "SY":"963", "TW": "886", "TZ": "255", "TL": "670", "TD": "235", "TJ": "992", "TH": "66", "TG":"228", "TK": "690", "TO": "676", "TT": "1", "TN":"216","TR": "90", "TM": "993", "TC": "1", "TV":"688", "UG": "256", "UA": "380", "US": "1", "UY": "598","UZ": "998", "VA":"379", "VE":"58", "VN": "84", "VG": "1", "VI": "1","VC":"1", "VU":"678", "WS": "685", "WF": "681", "YE": "967", "YT": "262","ZA": "27" , "ZM": "260", "ZW":"263"]
let countryDialingCode = prefixCodes[countryRegionCode]
return countryDialingCode!
}
And call as
let currentLocale = NSLocale.currentLocale()
let countryCode = currentLocale.objectForKey(NSLocaleCountryCode) as! String//get the set country name, code of your iphone
print("country code is \(countryCode)")
print(getCountryCallingCode(countryCode))
//change country region Settings>>General>>Language&Region>>Region
Swift
let networkInfo = CTTelephonyNetworkInfo()
if let carrier = networkInfo.subscriberCellularProvider {
print("country code is: " + carrier.mobileCountryCode!);
//will return the actual country code
print("ISO country code is: " + carrier.isoCountryCode!);
}
Swift 5
I combine answer from Oded and LC into a function.
func getCountryCode() -> String {
guard let carrier = CTTelephonyNetworkInfo().subscriberCellularProvider, let countryCode = carrier.isoCountryCode else { return "" }
let prefixCodes = ["AF": "93", "AE": "971", "AL": "355", "AN": "599", "AS":"1", "AD": "376", "AO": "244", "AI": "1", "AG":"1", "AR": "54","AM": "374", "AW": "297", "AU":"61", "AT": "43","AZ": "994", "BS": "1", "BH":"973", "BF": "226","BI": "257", "BD": "880", "BB": "1", "BY": "375", "BE":"32","BZ": "501", "BJ": "229", "BM": "1", "BT":"975", "BA": "387", "BW": "267", "BR": "55", "BG": "359", "BO": "591", "BL": "590", "BN": "673", "CC": "61", "CD":"243","CI": "225", "KH":"855", "CM": "237", "CA": "1", "CV": "238", "KY":"345", "CF":"236", "CH": "41", "CL": "56", "CN":"86","CX": "61", "CO": "57", "KM": "269", "CG":"242", "CK": "682", "CR": "506", "CU":"53", "CY":"537","CZ": "420", "DE": "49", "DK": "45", "DJ":"253", "DM": "1", "DO": "1", "DZ": "213", "EC": "593", "EG":"20", "ER": "291", "EE":"372","ES": "34", "ET": "251", "FM": "691", "FK": "500", "FO": "298", "FJ": "679", "FI":"358", "FR": "33", "GB":"44", "GF": "594", "GA":"241", "GS": "500", "GM":"220", "GE":"995","GH":"233", "GI": "350", "GQ": "240", "GR": "30", "GG": "44", "GL": "299", "GD":"1", "GP": "590", "GU": "1", "GT": "502", "GN":"224","GW": "245", "GY": "595", "HT": "509", "HR": "385", "HN":"504", "HU": "36", "HK": "852", "IR": "98", "IM": "44", "IL": "972", "IO":"246", "IS": "354", "IN": "91", "ID":"62", "IQ":"964", "IE": "353","IT":"39", "JM":"1", "JP": "81", "JO": "962", "JE":"44", "KP": "850", "KR": "82","KZ":"77", "KE": "254", "KI": "686", "KW": "965", "KG":"996","KN":"1", "LC": "1", "LV": "371", "LB": "961", "LK":"94", "LS": "266", "LR":"231", "LI": "423", "LT": "370", "LU": "352", "LA": "856", "LY":"218", "MO": "853", "MK": "389", "MG":"261", "MW": "265", "MY": "60","MV": "960", "ML":"223", "MT": "356", "MH": "692", "MQ": "596", "MR":"222", "MU": "230", "MX": "52","MC": "377", "MN": "976", "ME": "382", "MP": "1", "MS": "1", "MA":"212", "MM": "95", "MF": "590", "MD":"373", "MZ": "258", "NA":"264", "NR":"674", "NP":"977", "NL": "31","NC": "687", "NZ":"64", "NI": "505", "NE": "227", "NG": "234", "NU":"683", "NF": "672", "NO": "47","OM": "968", "PK": "92", "PM": "508", "PW": "680", "PF": "689", "PA": "507", "PG":"675", "PY": "595", "PE": "51", "PH": "63", "PL":"48", "PN": "872","PT": "351", "PR": "1","PS": "970", "QA": "974", "RO":"40", "RE":"262", "RS": "381", "RU": "7", "RW": "250", "SM": "378", "SA":"966", "SN": "221", "SC": "248", "SL":"232","SG": "65", "SK": "421", "SI": "386", "SB":"677", "SH": "290", "SD": "249", "SR": "597","SZ": "268", "SE":"46", "SV": "503", "ST": "239","SO": "252", "SJ": "47", "SY":"963", "TW": "886", "TZ": "255", "TL": "670", "TD": "235", "TJ": "992", "TH": "66", "TG":"228", "TK": "690", "TO": "676", "TT": "1", "TN":"216","TR": "90", "TM": "993", "TC": "1", "TV":"688", "UG": "256", "UA": "380", "US": "1", "UY": "598","UZ": "998", "VA":"379", "VE":"58", "VN": "84", "VG": "1", "VI": "1","VC":"1", "VU":"678", "WS": "685", "WF": "681", "YE": "967", "YT": "262","ZA": "27" , "ZM": "260", "ZW":"263"]
let countryDialingCode = prefixCodes[countryCode.uppercased()] ?? ""
return countryDialingCode
}
Make sure to import CoreTelephony at the top
import CoreTelephony
I think you need to use NSLocale for using Country code of the user.
You can follow this link to understand use of NSLocale class reference.
Also study this link for ISOCountryCode property.
Hope this may help you.
I came up with the following code, based on previous answers:
Swift
#if canImport(CoreTelephony)
import CoreTelephony
#endif
static func getRegionCodeFromSim() -> String? {
#if canImport(CoreTelephony)
let networkInfos = CTTelephonyNetworkInfo()
if #available(iOS 12, *) {
let carrier = networkInfos.serviceSubscriberCellularProviders?
.map { $0.1 }
.first { $0.isoCountryCode != nil }
return carrier?.isoCountryCode
}
return networkInfos.subscriberCellularProvider?.isoCountryCode
#else
return nil
#endif
}
static func getRegionCode() -> String? {
guard let regionCodeFromSim = Self.getRegionCodeFromSim() else {
return NSLocale.current.regionCode
}
return regionCodeFromSim
}
static func getCountryCode() -> String? {
guard let regionCode = Self.getRegionCode() else { return nil }
let prefixCodes = ["AF": "93", "AE": "971", "AL": "355", "AN": "599", "AS":"1", "AD": "376", "AO": "244", "AI": "1", "AG":"1", "AR": "54","AM": "374", "AW": "297", "AU":"61", "AT": "43","AZ": "994", "BS": "1", "BH":"973", "BF": "226","BI": "257", "BD": "880", "BB": "1", "BY": "375", "BE":"32","BZ": "501", "BJ": "229", "BM": "1", "BT":"975", "BA": "387", "BW": "267", "BR": "55", "BG": "359", "BO": "591", "BL": "590", "BN": "673", "CC": "61", "CD":"243","CI": "225", "KH":"855", "CM": "237", "CA": "1", "CV": "238", "KY":"345", "CF":"236", "CH": "41", "CL": "56", "CN":"86","CX": "61", "CO": "57", "KM": "269", "CG":"242", "CK": "682", "CR": "506", "CU":"53", "CY":"537","CZ": "420", "DE": "49", "DK": "45", "DJ":"253", "DM": "1", "DO": "1", "DZ": "213", "EC": "593", "EG":"20", "ER": "291", "EE":"372","ES": "34", "ET": "251", "FM": "691", "FK": "500", "FO": "298", "FJ": "679", "FI":"358", "FR": "33", "GB":"44", "GF": "594", "GA":"241", "GS": "500", "GM":"220", "GE":"995","GH":"233", "GI": "350", "GQ": "240", "GR": "30", "GG": "44", "GL": "299", "GD":"1", "GP": "590", "GU": "1", "GT": "502", "GN":"224","GW": "245", "GY": "595", "HT": "509", "HR": "385", "HN":"504", "HU": "36", "HK": "852", "IR": "98", "IM": "44", "IL": "972", "IO":"246", "IS": "354", "IN": "91", "ID":"62", "IQ":"964", "IE": "353","IT":"39", "JM":"1", "JP": "81", "JO": "962", "JE":"44", "KP": "850", "KR": "82","KZ":"77", "KE": "254", "KI": "686", "KW": "965", "KG":"996","KN":"1", "LC": "1", "LV": "371", "LB": "961", "LK":"94", "LS": "266", "LR":"231", "LI": "423", "LT": "370", "LU": "352", "LA": "856", "LY":"218", "MO": "853", "MK": "389", "MG":"261", "MW": "265", "MY": "60","MV": "960", "ML":"223", "MT": "356", "MH": "692", "MQ": "596", "MR":"222", "MU": "230", "MX": "52","MC": "377", "MN": "976", "ME": "382", "MP": "1", "MS": "1", "MA":"212", "MM": "95", "MF": "590", "MD":"373", "MZ": "258", "NA":"264", "NR":"674", "NP":"977", "NL": "31","NC": "687", "NZ":"64", "NI": "505", "NE": "227", "NG": "234", "NU":"683", "NF": "672", "NO": "47","OM": "968", "PK": "92", "PM": "508", "PW": "680", "PF": "689", "PA": "507", "PG":"675", "PY": "595", "PE": "51", "PH": "63", "PL":"48", "PN": "872","PT": "351", "PR": "1","PS": "970", "QA": "974", "RO":"40", "RE":"262", "RS": "381", "RU": "7", "RW": "250", "SM": "378", "SA":"966", "SN": "221", "SC": "248", "SL":"232","SG": "65", "SK": "421", "SI": "386", "SB":"677", "SH": "290", "SD": "249", "SR": "597","SZ": "268", "SE":"46", "SV": "503", "ST": "239","SO": "252", "SJ": "47", "SY":"963", "TW": "886", "TZ": "255", "TL": "670", "TD": "235", "TJ": "992", "TH": "66", "TG":"228", "TK": "690", "TO": "676", "TT": "1", "TN":"216","TR": "90", "TM": "993", "TC": "1", "TV":"688", "UG": "256", "UA": "380", "US": "1", "UY": "598","UZ": "998", "VA":"379", "VE":"58", "VN": "84", "VG": "1", "VI": "1","VC":"1", "VU":"678", "WS": "685", "WF": "681", "YE": "967", "YT": "262","ZA": "27" , "ZM": "260", "ZW":"263"]
return prefixCodes[regionCode.uppercased()]
}
It tries to fetch the country code from the SIM cards (with multi-sim & non-sim devices support), if available, and fallbacks to the device's locale otherwise.
The prefixCodes could be loaded from a PLIST or JSON to help with readability.
If you want to prefixed calling country code automatically
then you need to get user's country code pragmatically and Drag & drop src Folder in your code
Its looks like this:
if let countryCode = (Locale.current as NSLocale).object(forKey: .countryCode) as? String {
print(countryCode)
let strCode = Countries.countryFromCountryCode(countryCode: countryCode)
btnPhoneCode.setTitle("+\(strCode.phoneExtension)", for: .normal)
}
It works for me, Hope will help you too. :)
NSLocale *currentLocale = [NSLocale currentLocale]; // get the current locale.
NSString *countryCode = [currentLocale objectForKey:NSLocaleCountryCode];
// get country code, e.g. ES (Spain), FR (France), etc.
NSLog(#"country code is:%#",countryCode);
NSString*lower=[countryCode lowercaseString];
NSString *path = [[NSBundle mainBundle] pathForResource:#"DiallingCodes" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSMutableDictionary *_dictCountry=[[NSMutableDictionary alloc]init];
NSMutableArray *_CodeArray=[[NSMutableArray alloc]init];
[_CodeArray addObject:dict];
_dictCountry = [_CodeArray objectAtIndex:0];
NSString*Country_code=[NSString stringWithFormat:#"+%#",[_dictCountry objectForKey:lower]];
contactTextField.text=Country_code;
You can request to this url.
For get CountryCode or ip, region_name, city, long, lat
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://freegeoip.net/json/"]];
__block NSDictionary *json;
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Countrycode: %#", json[#"country_code"]);
}];
Here the Objective C code
#import<CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
- (void)viewDidLoad{
CTTelephonyNetworkInfo *network_Info = [CTTelephonyNetworkInfo new];
CTCarrier *carrier = network_Info.subscriberCellularProvider;
NSLog(#"country code is: %#", carrier.mobileCountryCode);
NSLog(#"ISO country code is: %#", carrier.mobileNetworkCode);
NSLog(#"diling code == %#",[self getCountryCode:carrier.isoCountryCode]);
}
- (NSString *)getCountryCode:(NSString *)countryISOCode{
NSDictionary * code = #{#"AF": #"93", #"AE": #"971", #"AL": #"355", #"AN": #"599", #"AS":#"1", #"AD": #"376", #"AO": #"244", #"AI": #"1", #"AG":#"1", #"AR": #"54",#"AM": #"374", #"AW": #"297", #"AU":#"61", #"AT": #"43",#"AZ": #"994", #"BS": #"1", #"BH":#"973", #"BF": #"226",#"BI": #"257", #"BD": #"880", #"BB": #"1", #"BY": #"375", #"BE":#"32",#"BZ": #"501", #"BJ": #"229", #"BM": #"1", #"BT":#"975", #"BA": #"387", #"BW": #"267", #"BR": #"55", #"BG": #"359", #"BO": #"591", #"BL": #"590", #"BN": #"673", #"CC": #"61", #"CD":#"243",#"CI": #"225", #"KH":#"855", #"CM": #"237", #"CA": #"1", #"CV": #"238", #"KY":#"345", #"CF":#"236", #"CH": #"41", #"CL": #"56", #"CN":#"86",#"CX": #"61", #"CO": #"57", #"KM": #"269", #"CG":#"242", #"CK": #"682", #"CR": #"506", #"CU":#"53", #"CY":#"537",#"CZ": #"420", #"DE": #"49", #"DK": #"45", #"DJ":#"253", #"DM": #"1", #"DO": #"1", #"DZ": #"213", #"EC": #"593", #"EG":#"20", #"ER": #"291", #"EE":#"372",#"ES": #"34", #"ET": #"251", #"FM": #"691", #"FK": #"500", #"FO": #"298", #"FJ": #"679", #"FI":#"358", #"FR": #"33", #"GB":#"44", #"GF": #"594", #"GA":#"241", #"GS": #"500", #"GM":#"220", #"GE":#"995",#"GH":#"233", #"GI": #"350", #"GQ": #"240", #"GR": #"30", #"GG": #"44", #"GL": #"299", #"GD":#"1", #"GP": #"590", #"GU": #"1", #"GT": #"502", #"GN":#"224",#"GW": #"245", #"GY": #"595", #"HT": #"509", #"HR": #"385", #"HN":#"504", #"HU": #"36", #"HK": #"852", #"IR": #"98", #"IM": #"44", #"IL": #"972", #"IO":#"246", #"IS": #"354", #"IN": #"91", #"ID":#"62", #"IQ":#"964", #"IE": #"353",#"IT":#"39", #"JM":#"1", #"JP": #"81", #"JO": #"962", #"JE":#"44", #"KP": #"850", #"KR": #"82",#"KZ":#"77", #"KE": #"254", #"KI": #"686", #"KW": #"965", #"KG":#"996",#"KN":#"1", #"LC": #"1", #"LV": #"371", #"LB": #"961", #"LK":#"94", #"LS": #"266", #"LR":#"231", #"LI": #"423", #"LT": #"370", #"LU": #"352", #"LA": #"856", #"LY":#"218", #"MO": #"853", #"MK": #"389", #"MG":#"261", #"MW": #"265", #"MY": #"60",#"MV": #"960", #"ML":#"223", #"MT": #"356", #"MH": #"692", #"MQ": #"596", #"MR":#"222", #"MU": #"230", #"MX": #"52",#"MC": #"377", #"MN": #"976", #"ME": #"382", #"MP": #"1", #"MS": #"1", #"MA":#"212", #"MM": #"95", #"MF": #"590", #"MD":#"373", #"MZ": #"258", #"NA":#"264", #"NR":#"674", #"NP":#"977", #"NL": #"31",#"NC": #"687", #"NZ":#"64", #"NI": #"505", #"NE": #"227", #"NG": #"234", #"NU":#"683", #"NF": #"672", #"NO": #"47",#"OM": #"968", #"PK": #"92", #"PM": #"508", #"PW": #"680", #"PF": #"689", #"PA": #"507", #"PG":#"675", #"PY": #"595", #"PE": #"51", #"PH": #"63", #"PL":#"48", #"PN": #"872",#"PT": #"351", #"PR": #"1",#"PS": #"970", #"QA": #"974", #"RO":#"40", #"RE":#"262", #"RS": #"381", #"RU": #"7", #"RW": #"250", #"SM": #"378", #"SA":#"966", #"SN": #"221", #"SC": #"248", #"SL":#"232",#"SG": #"65", #"SK": #"421", #"SI": #"386", #"SB":#"677", #"SH": #"290", #"SD": #"249", #"SR": #"597",#"SZ": #"268", #"SE":#"46", #"SV": #"503", #"ST": #"239",#"SO": #"252", #"SJ": #"47", #"SY":#"963", #"TW": #"886", #"TZ": #"255", #"TL": #"670", #"TD": #"235", #"TJ": #"992", #"TH": #"66", #"TG":#"228", #"TK": #"690", #"TO": #"676", #"TT": #"1", #"TN":#"216",#"TR": #"90", #"TM": #"993", #"TC": #"1", #"TV":#"688", #"UG": #"256", #"UA": #"380", #"US": #"1", #"UY": #"598",#"UZ": #"998", #"VA":#"379", #"VE":#"58", #"VN": #"84", #"VG": #"1", #"VI": #"1",#"VC":#"1", #"VU":#"678", #"WS": #"685", #"WF": #"681", #"YE": #"967", #"YT": #"262",#"ZA": #"27" , #"ZM": #"260", #"ZW":#"263"};
return [NSString stringWithFormat:#"+%#", [code objectForKey:[countryISOCode uppercaseString]]];
}
Swift 5 Support and using optionals here is my solution:
static func GetCountryCallingCode(countryRegionCode:String) -> String? {
let prefixCodes = ["AF": "93", "AE": "971", "AL": "355", "AN": "599", "AS":"1", "AD": "376", "AO": "244", "AI": "1", "AG":"1", "AR": "54","AM": "374", "AW": "297", "AU":"61", "AT": "43","AZ": "994", "BS": "1", "BH":"973", "BF": "226","BI": "257", "BD": "880", "BB": "1", "BY": "375", "BE":"32","BZ": "501", "BJ": "229", "BM": "1", "BT":"975", "BA": "387", "BW": "267", "BR": "55", "BG": "359", "BO": "591", "BL": "590", "BN": "673", "CC": "61", "CD":"243","CI": "225", "KH":"855", "CM": "237", "CA": "1", "CV": "238", "KY":"345", "CF":"236", "CH": "41", "CL": "56", "CN":"86","CX": "61", "CO": "57", "KM": "269", "CG":"242", "CK": "682", "CR": "506", "CU":"53", "CY":"537","CZ": "420", "DE": "49", "DK": "45", "DJ":"253", "DM": "1", "DO": "1", "DZ": "213", "EC": "593", "EG":"20", "ER": "291", "EE":"372","ES": "34", "ET": "251", "FM": "691", "FK": "500", "FO": "298", "FJ": "679", "FI":"358", "FR": "33", "GB":"44", "GF": "594", "GA":"241", "GS": "500", "GM":"220", "GE":"995","GH":"233", "GI": "350", "GQ": "240", "GR": "30", "GG": "44", "GL": "299", "GD":"1", "GP": "590", "GU": "1", "GT": "502", "GN":"224","GW": "245", "GY": "595", "HT": "509", "HR": "385", "HN":"504", "HU": "36", "HK": "852", "IR": "98", "IM": "44", "IL": "972", "IO":"246", "IS": "354", "IN": "91", "ID":"62", "IQ":"964", "IE": "353","IT":"39", "JM":"1", "JP": "81", "JO": "962", "JE":"44", "KP": "850", "KR": "82","KZ":"77", "KE": "254", "KI": "686", "KW": "965", "KG":"996","KN":"1", "LC": "1", "LV": "371", "LB": "961", "LK":"94", "LS": "266", "LR":"231", "LI": "423", "LT": "370", "LU": "352", "LA": "856", "LY":"218", "MO": "853", "MK": "389", "MG":"261", "MW": "265", "MY": "60","MV": "960", "ML":"223", "MT": "356", "MH": "692", "MQ": "596", "MR":"222", "MU": "230", "MX": "52","MC": "377", "MN": "976", "ME": "382", "MP": "1", "MS": "1", "MA":"212", "MM": "95", "MF": "590", "MD":"373", "MZ": "258", "NA":"264", "NR":"674", "NP":"977", "NL": "31","NC": "687", "NZ":"64", "NI": "505", "NE": "227", "NG": "234", "NU":"683", "NF": "672", "NO": "47","OM": "968", "PK": "92", "PM": "508", "PW": "680", "PF": "689", "PA": "507", "PG":"675", "PY": "595", "PE": "51", "PH": "63", "PL":"48", "PN": "872","PT": "351", "PR": "1","PS": "970", "QA": "974", "RO":"40", "RE":"262", "RS": "381", "RU": "7", "RW": "250", "SM": "378", "SA":"966", "SN": "221", "SC": "248", "SL":"232","SG": "65", "SK": "421", "SI": "386", "SB":"677", "SH": "290", "SD": "249", "SR": "597","SZ": "268", "SE":"46", "SV": "503", "ST": "239","SO": "252", "SJ": "47", "SY":"963", "TW": "886", "TZ": "255", "TL": "670", "TD": "235", "TJ": "992", "TH": "66", "TG":"228", "TK": "690", "TO": "676", "TT": "1", "TN":"216","TR": "90", "TM": "993", "TC": "1", "TV":"688", "UG": "256", "UA": "380", "US": "1", "UY": "598","UZ": "998", "VA":"379", "VE":"58", "VN": "84", "VG": "1", "VI": "1","VC":"1", "VU":"678", "WS": "685", "WF": "681", "YE": "967", "YT": "262","ZA": "27" , "ZM": "260", "ZW":"263"]
let countryDialingCode = prefixCodes[countryRegionCode]
return countryDialingCode
}
guard let regionCode = NSLocale.current.regionCode,
let callingCode = GetCountryCallingCode(countryRegionCode: regionCode )
else { return }
print("Region: \(regionCode) Country calling code is \(callingCode)")
import CoreTelephony
/// Method to get the iso calling code
///
/// - Returns: String
public static func getCallingCodePrefix() -> String {
let networkInfo = CTTelephonyNetworkInfo()
let phoneNumberKit = PhoneNumberKit()
if #available(iOS 12.0, *) {
if let carrier = networkInfo.serviceSubscriberCellularProviders?.map({ $0.1 }).first(where: { $0.isoCountryCode != nil }), let isoCode = carrier.isoCountryCode?.uppercased(), let prefixCode = phoneNumberKit.countryCode(for: isoCode) {
return "+" + String(prefixCode)
}
} else {
// Fallback on earlier versions
if let carrier = networkInfo.subscriberCellularProvider, let isoCode = carrier.isoCountryCode?.uppercased(), let prefixCode = phoneNumberKit.countryCode(for: isoCode) {
return "+" + String(prefixCode)
}
}
return "+"
}
Use this code to get the user's country in iOS:
func countryName(from countryCode: String) -> String {
if let name = (Locale.current as NSLocale).displayName(forKey: .countryCode, value: countryCode) {
return name
} else {
return countryCode
}
}
//Locale.current.regionCode this is used for Get user current country region code
countryName(from: Locale.current.regionCode ?? "")

How to get country phone code for given country name in Swift iOS?

I'm working on a project
I need to send the selected phone number (which user selected already from phone contacts list) to the sever with format :
international-code-without-zeros-or-plus_the-number
so I need to handle many cases : number without international code , number with zeros , number with plus , number with two zeros ..etc
the problem is when I have a local phone number unprecedented by country phone code,I could get the current country name (country name code) if the device has a valid sim card via this code
let networkInfo: CTTelephonyNetworkInfo = CTTelephonyNetworkInfo()
let ar = networkInfo.subscriberCellularProvider
if ar != nil {
if let mcc = ar.mobileCountryCode {
myInformation.countryCode = mcc
}
then how can I get the country phone code??
class func getCountryPhonceCode (_ country : String) -> String
{
var countryDictionary = ["AF":"93",
"AL":"355",
"DZ":"213",
"AS":"1",
"AD":"376",
"AO":"244",
"AI":"1",
"AG":"1",
"AR":"54",
"AM":"374",
"AW":"297",
"AU":"61",
"AT":"43",
"AZ":"994",
"BS":"1",
"BH":"973",
"BD":"880",
"BB":"1",
"BY":"375",
"BE":"32",
"BZ":"501",
"BJ":"229",
"BM":"1",
"BT":"975",
"BA":"387",
"BW":"267",
"BR":"55",
"IO":"246",
"BG":"359",
"BF":"226",
"BI":"257",
"KH":"855",
"CM":"237",
"CA":"1",
"CV":"238",
"KY":"345",
"CF":"236",
"TD":"235",
"CL":"56",
"CN":"86",
"CX":"61",
"CO":"57",
"KM":"269",
"CG":"242",
"CK":"682",
"CR":"506",
"HR":"385",
"CU":"53",
"CY":"537",
"CZ":"420",
"DK":"45",
"DJ":"253",
"DM":"1",
"DO":"1",
"EC":"593",
"EG":"20",
"SV":"503",
"GQ":"240",
"ER":"291",
"EE":"372",
"ET":"251",
"FO":"298",
"FJ":"679",
"FI":"358",
"FR":"33",
"GF":"594",
"PF":"689",
"GA":"241",
"GM":"220",
"GE":"995",
"DE":"49",
"GH":"233",
"GI":"350",
"GR":"30",
"GL":"299",
"GD":"1",
"GP":"590",
"GU":"1",
"GT":"502",
"GN":"224",
"GW":"245",
"GY":"595",
"HT":"509",
"HN":"504",
"HU":"36",
"IS":"354",
"IN":"91",
"ID":"62",
"IQ":"964",
"IE":"353",
"IL":"972",
"IT":"39",
"JM":"1",
"JP":"81",
"JO":"962",
"KZ":"77",
"KE":"254",
"KI":"686",
"KW":"965",
"KG":"996",
"LV":"371",
"LB":"961",
"LS":"266",
"LR":"231",
"LI":"423",
"LT":"370",
"LU":"352",
"MG":"261",
"MW":"265",
"MY":"60",
"MV":"960",
"ML":"223",
"MT":"356",
"MH":"692",
"MQ":"596",
"MR":"222",
"MU":"230",
"YT":"262",
"MX":"52",
"MC":"377",
"MN":"976",
"ME":"382",
"MS":"1",
"MA":"212",
"MM":"95",
"NA":"264",
"NR":"674",
"NP":"977",
"NL":"31",
"AN":"599",
"NC":"687",
"NZ":"64",
"NI":"505",
"NE":"227",
"NG":"234",
"NU":"683",
"NF":"672",
"MP":"1",
"NO":"47",
"OM":"968",
"PK":"92",
"PW":"680",
"PA":"507",
"PG":"675",
"PY":"595",
"PE":"51",
"PH":"63",
"PL":"48",
"PT":"351",
"PR":"1",
"QA":"974",
"RO":"40",
"RW":"250",
"WS":"685",
"SM":"378",
"SA":"966",
"SN":"221",
"RS":"381",
"SC":"248",
"SL":"232",
"SG":"65",
"SK":"421",
"SI":"386",
"SB":"677",
"ZA":"27",
"GS":"500",
"ES":"34",
"LK":"94",
"SD":"249",
"SR":"597",
"SZ":"268",
"SE":"46",
"CH":"41",
"TJ":"992",
"TH":"66",
"TG":"228",
"TK":"690",
"TO":"676",
"TT":"1",
"TN":"216",
"TR":"90",
"TM":"993",
"TC":"1",
"TV":"688",
"UG":"256",
"UA":"380",
"AE":"971",
"GB":"44",
"US":"1",
"UY":"598",
"UZ":"998",
"VU":"678",
"WF":"681",
"YE":"967",
"ZM":"260",
"ZW":"263",
"BO":"591",
"BN":"673",
"CC":"61",
"CD":"243",
"CI":"225",
"FK":"500",
"GG":"44",
"VA":"379",
"HK":"852",
"IR":"98",
"IM":"44",
"JE":"44",
"KP":"850",
"KR":"82",
"LA":"856",
"LY":"218",
"MO":"853",
"MK":"389",
"FM":"691",
"MD":"373",
"MZ":"258",
"PS":"970",
"PN":"872",
"RE":"262",
"RU":"7",
"BL":"590",
"SH":"290",
"KN":"1",
"LC":"1",
"MF":"590",
"PM":"508",
"VC":"1",
"ST":"239",
"SO":"252",
"SJ":"47",
"SY":"963",
"TW":"886",
"TZ":"255",
"TL":"670",
"VE":"58",
"VN":"84",
"VG":"284",
"VI":"340"]
if let countryCode = countryDictionary[country] {
return countryCode
}
return ""
}
My suggested answer is something like brute force method !
is to list all country names and its matched country phone code in a dictionary and use searching function that gives me the matched phone code to a specific country code
func getCountryPhonceCode (country : String) -> String
{
if count(country) == 2
{
let x : [String] = ["972", "IL",
"93" , "AF",
"355", "AL",
"213", "DZ",
"1" , "AS",
"376", "AD",
"244", "AO",
"1" , "AI",
"1" , "AG",
"54" , "AR",
"374", "AM",
"297", "AW",
"61" , "AU",
"43" , "AT",
"994", "AZ",
"1" , "BS",
"973", "BH",
"880", "BD",
"1" , "BB",
"375", "BY",
"32" , "BE",
"501", "BZ",
"229", "BJ",
"1" , "BM",
"975", "BT",
"387", "BA",
"267", "BW",
"55" , "BR",
"246", "IO",
"359", "BG",
"226", "BF",
"257", "BI",
"855", "KH",
"237", "CM",
"1" , "CA",
"238", "CV",
"345", "KY",
"236", "CF",
"235", "TD",
"56", "CL",
"86", "CN",
"61", "CX",
"57", "CO",
"269", "KM",
"242", "CG",
"682", "CK",
"506", "CR",
"385", "HR",
"53" , "CU" ,
"537", "CY",
"420", "CZ",
"45" , "DK" ,
"253", "DJ",
"1" , "DM",
"1" , "DO",
"593", "EC",
"20" , "EG" ,
"503", "SV",
"240", "GQ",
"291", "ER",
"372", "EE",
"251", "ET",
"298", "FO",
"679", "FJ",
"358", "FI",
"33" , "FR",
"594", "GF",
"689", "PF",
"241", "GA",
"220", "GM",
"995", "GE",
"49" , "DE",
"233", "GH",
"350", "GI",
"30" , "GR",
"299", "GL",
"1" , "GD",
"590", "GP",
"1" , "GU",
"502", "GT",
"224", "GN",
"245", "GW",
"595", "GY",
"509", "HT",
"504", "HN",
"36" , "HU",
"354", "IS",
"91" , "IN",
"62" , "ID",
"964", "IQ",
"353", "IE",
"972", "IL",
"39" , "IT",
"1" , "JM",
"81", "JP", "962", "JO", "77", "KZ",
"254", "KE", "686", "KI", "965", "KW", "996", "KG",
"371", "LV", "961", "LB", "266", "LS", "231", "LR",
"423", "LI", "370", "LT", "352", "LU", "261", "MG",
"265", "MW", "60", "MY", "960", "MV", "223", "ML",
"356", "MT", "692", "MH", "596", "MQ", "222", "MR",
"230", "MU", "262", "YT", "52","MX", "377", "MC",
"976", "MN", "382", "ME", "1", "MS", "212", "MA",
"95", "MM", "264", "NA", "674", "NR", "977", "NP",
"31", "NL", "599", "AN", "687", "NC", "64", "NZ",
"505", "NI", "227", "NE", "234", "NG", "683", "NU",
"672", "NF", "1", "MP", "47", "NO", "968", "OM",
"92", "PK", "680", "PW", "507", "PA", "675", "PG",
"595", "PY", "51", "PE", "63", "PH", "48", "PL",
"351", "PT", "1", "PR", "974", "QA", "40", "RO",
"250", "RW", "685", "WS", "378", "SM", "966", "SA",
"221", "SN", "381", "RS", "248", "SC", "232", "SL",
"65", "SG", "421", "SK", "386", "SI", "677", "SB",
"27", "ZA", "500", "GS", "34", "ES", "94", "LK",
"249", "SD", "597", "SR", "268", "SZ", "46", "SE",
"41", "CH", "992", "TJ", "66", "TH", "228", "TG",
"690", "TK", "676", "TO", "1", "TT", "216", "TN",
"90", "TR", "993", "TM", "1", "TC", "688", "TV",
"256", "UG", "380", "UA", "971", "AE", "44", "GB",
"1", "US", "598", "UY", "998", "UZ", "678", "VU",
"681", "WF", "967", "YE", "260", "ZM", "263", "ZW",
"591", "BO", "673", "BN", "61", "CC", "243", "CD",
"225", "CI", "500", "FK", "44", "GG", "379", "VA",
"852", "HK", "98", "IR", "44", "IM", "44", "JE",
"850", "KP", "82", "KR", "856", "LA", "218", "LY",
"853", "MO", "389", "MK", "691", "FM", "373", "MD",
"258", "MZ", "970", "PS", "872", "PN", "262", "RE",
"7", "RU", "590", "BL", "290", "SH", "1", "KN",
"1", "LC", "590", "MF", "508", "PM", "1", "VC",
"239", "ST", "252", "SO", "47", "SJ",
"963","SY",
"886",
"TW", "255",
"TZ", "670",
"TL","58",
"VE","84",
"VN",
"284", "VG",
"340", "VI",
"678","VU",
"681","WF",
"685","WS",
"967","YE",
"262","YT",
"27","ZA",
"260","ZM",
"263","ZW"]
var keys = [String]()
var values = [String]()
let whitespace = NSCharacterSet.decimalDigitCharacterSet()
//let range = phrase.rangeOfCharacterFromSet(whitespace)
for i in x {
// range will be nil if no whitespace is found
if (i.rangeOfCharacterFromSet(whitespace) != nil) {
values.append(i)
}
else {
keys.append(i)
}
}
var countryCodeListDict = NSDictionary(objects: values as [String], forKeys: keys as [String])
if let t: AnyObject = countryCodeListDict[country] {
return countryCodeListDict[country] as! String
} else
{
return ""
}
}
else
{
return ""
}
}
I made help class for it and I made an example app
import Foundation
public class Countries {
// MARK: - var and let
// MARK: - functions
public static func getAllCountries() -> [Country] {
var countries = [Country]()
NSLocale.ISOCountryCodes().forEach { (isoCode) in
guard let countryName = NSLocale.currentLocale().displayNameForKey(NSLocaleCountryCode, value: isoCode) else { return }
if let countryInfo = countryInfoDictionary[isoCode] {
let phoneExtension = countryInfo["phoneExtension"] as! String
let isMain = countryInfo["isMain"] as! Bool
countries.append(Country(name: countryName, phoneExtension: phoneExtension, countryCode: isoCode, isMain: isMain))
} else {
countries.append(Country(name: countryName, phoneExtension: nil, countryCode: isoCode, isMain: nil))
}
}
return countries
}
public static func getCountriesByFirstLetter() -> [(String, [Country])] {
let countries = getAllCountries()
var countryDictionary = [String : [Country]]()
var countryFirstLetterArray = [String]()
countries.forEach { (country) in
let letterIndex = country.name.startIndex.advancedBy(0)
countryFirstLetterArray.append(String(country.name[letterIndex]))
if countryFirstLetterArray.count == 249 {
countryFirstLetterArray = Array(Set(countryFirstLetterArray))
countryFirstLetterArray.sortInPlace({ (firstString, secondString) -> Bool in
firstString < secondString
})
}
}
//
countryFirstLetterArray.forEach { (letter) in
countries.forEach({ (country) in
let letterIndex = country.name.startIndex.advancedBy(0)
let firsNameLetter = String(country.name[letterIndex])
if firsNameLetter == letter {
if var countries = countryDictionary[letter] {
countries.append(country)
countryDictionary[letter] = countries
} else {
countryDictionary[letter] = [country]
}
}
})
}
// sorting
let returnedCountries = countryDictionary.sort({$0.0 < $1.0})
return returnedCountries
}
public static func getCountriesWithPhone() -> [Country] {
var countries = getCountriesWithPhoneCode()
countries.sortInPlace({$0.name < $1.name})
return countries
}
public static func getCountriesByPhoneCode() -> [Country] {
var countries = getCountriesWithPhoneCode()
countries.sortInPlace({$0.phoneExtension! < $1.phoneExtension})
return countries
}
private static func getCountriesWithPhoneCode() -> [Country] {
let countries = getAllCountries()
var returnedCountries = [Country]()
countries.forEach { (country) in
if country.phoneExtension != nil {
returnedCountries.append(country)
}
}
return returnedCountries
}
}
extension Countries {
public static var countryInfoDictionary = ["AF" : ["phoneExtension" : "93", "isMain" : true], "AL" : ["phoneExtension" : "355", "isMain" : true], "DZ" : ["phoneExtension" : "213", "isMain" : true], "AS" : ["phoneExtension" : "1", "isMain" : false], "AD" : ["phoneExtension" : "376", "isMain" : true], "AO" :["phoneExtension" : "244", "isMain" : true], "AI" : ["phoneExtension" : "1", "isMain" : false], "AQ" : ["phoneExtension" : "672", "isMain" : true], "AG" : ["phoneExtension" : "1", "isMain" : false], "AR" : ["phoneExtension" : "54", "isMain" : true], "AM" : ["phoneExtension" : "374", "isMain" : true], "AW" : ["phoneExtension" : "297", "isMain" : true], "AU" : ["phoneExtension" : "61", "isMain" : true], "AT" : ["phoneExtension" : "43", "isMain" : true], "AZ": ["phoneExtension" : "994", "isMain" : true], "BS" : ["phoneExtension" : "1", "isMain" : false], "BH" : ["phoneExtension" : "973", "isMain": true], "BD" : ["phoneExtension" : "880", "isMain": true], "BB" : ["phoneExtension" : "1", "isMain": false], "BY" : ["phoneExtension" : "375", "isMain" : true], "BE" : ["phoneExtension": "32", "isMain": true], "BZ" : ["phoneExtension": "501", "isMain": true], "BJ" : ["phoneExtension" : "229", "isMain" : true], "BM" : ["phoneExtension" : "1", "isMain": false], "BT" : ["phoneExtension": "975", "isMain": true], "BO" : ["phoneExtension" : "591", "isMain": true], "BA" : ["phoneExtension" : "387", "isMain" : true], "BW" : ["phoneExtension" : "267", "isMain": true], "BR" : ["phoneExtension": "55", "isMain": true], "IO" : ["phoneExtension": "246", "isMain": true], "VG" : ["phoneExtension": "1", "isMain": false], "BN" : ["phoneExtension": "673", "isMain": true], "BG" : ["phoneExtension": "359", "isMain": true], "BF" :["phoneExtension": "226", "isMain": true], "BI" : ["phoneExtension": "257", "isMain": true], "KH" : ["phoneExtension": "855", "isMain": true], "CM" : ["phoneExtension": "237", "isMain": true], "CA" : ["phoneExtension": "1", "isMain": false], "CV" : ["phoneExtension" : "238", "isMain" : true], "KY" : ["phoneExtension" : "1", "isMain": false], "CF" : ["phoneExtension": "236", "isMain": true], "TD" : ["phoneExtension": "235", "isMain": true], "CL" : ["phoneExtension": "56", "isMain": true], "CN" : ["phoneExtension" : "86", "isMain": true], "CX" : ["phoneExtension" : "61", "isMain" : false], "CC" : ["phoneExtension" : "61", "isMain": false], "CO" : ["phoneExtension" : "57", "isMain": true], "KM" : ["phoneExtension": "269", "isMain": true], "CK" : ["phoneExtension": "682", "isMain": true], "CR" : ["phoneExtension" : "506", "isMain": true], "HR" : ["phoneExtension": "385", "isMain" : true], "CU" : ["phoneExtension": "53", "isMain": true], "CW" : ["phoneExtension": "599", "isMain": true], "CY" : ["phoneExtension" : "357", "isMain": true], "CZ" : ["phoneExtension": "420", "isMain": true], "CD" :["phoneExtension": "243", "isMain": true], "DK" : ["phoneExtension": "45", "isMain": true], "DJ" : ["phoneExtension" : "253", "isMain": true], "DM" : ["phoneExtension": "1", "isMain": false], "DO" : ["phoneExtension" : "1", "isMain": false], "TL" : ["phoneExtension": "670", "isMain": true], "EC" : ["phoneExtension" : "593", "isMain": true], "EG" : ["phoneExtension": "20", "isMain": true], "SV" : ["phoneExtension" : "503", "isMain" : true], "GQ" : ["phoneExtension" : "240", "isMain": true], "ER" : ["phoneExtension" : "291", "isMain": true], "EE" : ["phoneExtension" : "372", "isMain": true], "ET" : ["phoneExtension" : "251", "isMain": true], "FK" : ["phoneExtension" : "500", "isMain": true], "FO" : ["phoneExtension": "298", "isMain": true], "FJ" : ["phoneExtension": "679", "isMain": true], "FI" : ["phoneExtension" : "358", "isMain": true], "FR" : ["phoneExtension" : "33", "isMain" : true], "PF" : ["phoneExtension" : "689", "isMain": true], "GA" : ["phoneExtension" : "241", "isMain": true], "GM" : ["phoneExtension" : "220", "isMain" : true], "GE" : ["phoneExtension": "995", "isMain": true], "DE" : ["phoneExtension" : "49", "isMain": true], "GH" : ["phoneExtension" : "233", "isMain": true], "GI" :["phoneExtension" : "350", "isMain": true], "GR" : ["phoneExtension": "30", "isMain": true], "GL" : ["phoneExtension": "299", "isMain": true], "GD" : ["phoneExtension": "1", "isMain": false], "GU" : ["phoneExtension": "1", "isMain": false], "GT" : ["phoneExtension": "502", "isMain": true], "GG" : ["phoneExtension": "44", "isMain": false], "GN" : ["phoneExtension": "224", "isMain": true], "GW" : ["phoneExtension" : "245", "isMain": true], "GY" : ["phoneExtension": "592", "isMain": true], "HT" : ["phoneExtension": "509", "isMain": true], "HN" : ["phoneExtension": "504", "isMain": true], "HK" : ["phoneExtension": "652", "isMain": true], "HU" : ["phoneExtension": "36", "isMain": true], "IS" :["phoneExtension": "354", "isMain": true], "IN" : ["phoneExtension": "91", "isMain": true], "ID" :["phoneExtension": "62", "isMain": true], "IR" : ["phoneExtension": "98", "isMain": true], "IQ" : ["phoneExtension" : "964", "isMain" : true], "IE" : ["phoneExtension": "353", "isMain": true], "IM" : ["phoneExtension": "44", "isMain": false], "IL" : ["phoneExtension": "972", "isMain": true], "IT" : ["phoneExtension": "39", "isMain": true], "CI" : ["phoneExtension": "225", "isMain": true], "JM" : ["phoneExtension": "1", "isMain": false], "JP" : ["phoneExtension": "81", "isMain": true], "JE" : ["phoneExtension": "44", "isMain": false], "JO" : ["phoneExtension" : "962", "isMain": true], "KZ" : ["phoneExtension" : "7", "isMain": false], "KE" : ["phoneExtension" : "254", "isMain": true], "KI" : ["phoneExtension" : "686", "isMain": true], "XK" : ["phoneExtension": "383", "isMain": true], "KW" : ["phoneExtension": "965", "isMain": true], "KG" : ["phoneExtension": "996", "isMain": true], "LA" : ["phoneExtension": "856", "isMain": true], "LV" : ["phoneExtension": "371", "isMain": true], "LB" : ["phoneExtension": "961", "isMain": true], "LS" : ["phoneExtension": "266", "isMain": true], "LR" : ["phoneExtension": "231", "isMain": true], "LY" : ["phoneExtension": "218", "isMain": true], "LI" : ["phoneExtension": "423", "isMain": true], "LT" : ["phoneExtension": "370", "isMain": true], "LU" : ["phoneExtension": "352", "isMain": true], "MO" : ["phoneExtension": "853", "isMain": true], "MK" : ["phoneExtension": "389", "isMain": true], "MG" : ["phoneExtension": "261", "isMain": true], "MW" : ["phoneExtension": "265", "isMain": true], "MY" : ["phoneExtension": "60", "isMain": true], "MV" : ["phoneExtension": "960", "isMain": true], "ML" : ["phoneExtension": "223", "isMain": true], "MT" : ["phoneExtension": "356", "isMain": true], "MH" : ["phoneExtension": "692", "isMain": true], "MR" : ["phoneExtension": "222", "isMain": true], "MU" : ["phoneExtension": "230", "isMain": true], "YT" : ["phoneExtension": "262", "isMain": true], "MX" : ["phoneExtension": "52", "isMain": true], "FM" : ["phoneExtension": "691", "isMain": true], "MD" : ["phoneExtension": "373", "isMain": true], "MC" : ["phoneExtension": "377", "isMain": true], "MN" : ["phoneExtension": "976", "isMain": true], "ME" : ["phoneExtension": "382", "isMain": true], "MS" : ["phoneExtension": "1", "isMain": false], "MA" : ["phoneExtension": "212", "isMain": true], "MZ" : ["phoneExtension": "258", "isMain": true], "MM" : ["phoneExtension": "95", "isMain": true], "NA": ["phoneExtension": "264", "isMain": true], "NR" : ["phoneExtension": "674", "isMain": true], "NP" : ["phoneExtension": "977", "isMain": true], "NL" : ["phoneExtension": "31", "isMain": true], "AN" : ["phoneExtension": "599", "isMain": true], "NC" : ["phoneExtension": "687", "isMain": true], "NZ" : ["phoneExtension": "64", "isMain": true], "NI" : ["phoneExtension": "505", "isMain": true], "NE" : ["phoneExtension": "227", "isMain": true], "NG" : ["phoneExtension": "234", "isMain": true], "NU" : ["phoneExtension": "683", "isMain": true], "KP" : ["phoneExtension": "850", "isMain": true], "MP" : ["phoneExtension": "1", "isMain": false], "NO" : ["phoneExtension": "47", "isMain": true], "OM" : ["phoneExtension": "968", "isMain": true], "PK" : ["phoneExtension": "92", "isMain": true], "PW" : ["phoneExtension": "680", "isMain": true], "PS" : ["phoneExtension": "970", "isMain": true], "PA" : ["phoneExtension": "507", "isMain": true], "PG" : ["phoneExtension": "675", "isMain": true], "PY" : ["phoneExtension": "595", "isMain": true], "PE" : ["phoneExtension": "51", "isMain": true], "PH" : ["phoneExtension": "63", "isMain": true], "PN" :["phoneExtension": "64", "isMain": false], "PL" : ["phoneExtension": "48", "isMain": true], "PT" : ["phoneExtension": "351", "isMain": true], "PR" : ["phoneExtension": "1", "isMain": false], "QA" : ["phoneExtension": "974", "isMain": true], "CG" : ["phoneExtension": "242", "isMain": true], "RE" : ["phoneExtension": "262", "isMain": false], "RO" : ["phoneExtension": "40", "isMain": true], "RU" : ["phoneExtension": "7", "isMain": true], "RW" : ["phoneExtension": "250", "isMain": true], "BL" : ["phoneExtension": "590", "isMain": true], "SH": ["phoneExtension": "290", "isMain": true], "KN" : ["phoneExtension": "1", "isMain": false], "LC" : ["phoneExtension": "1", "isMain": false], "MF" : ["phoneExtension": "590", "isMain": false], "PM" : ["phoneExtension": "508", "isMain": true], "VC": ["phoneExtension": "1", "isMain": false], "WS" : ["phoneExtension": "685", "isMain": true], "SM" : ["phoneExtension": "378", "isMain": true], "ST" : ["phoneExtension": "239", "isMain": true], "SA" : ["phoneExtension": "966", "isMain": true], "SN" : ["phoneExtension": "221", "isMain": true], "RS" : ["phoneExtension": "381", "isMain": true], "SC" : ["phoneExtension": "248", "isMain": true], "SL" : ["phoneExtension": "232", "isMain": true], "SG" : ["phoneExtension": "65", "isMain": true], "SX" : ["phoneExtension": "1", "isMain": false], "SK" : ["phoneExtension": "421", "isMain": true], "SI" : ["phoneExtension": "386", "isMain": true], "SB" : ["phoneExtension": "677", "isMain": true], "SO" : ["phoneExtension": "252", "isMain": true], "ZA" : ["phoneExtension": "27", "isMain": true], "KR" : ["phoneExtension": "82", "isMain": true], "SS" : ["phoneExtension": "211", "isMain": true], "ES" : ["phoneExtension": "34", "isMain": true], "LK" : ["phoneExtension": "94", "isMain": true], "SD" : ["phoneExtension": "249", "isMain": true], "SR" : ["phoneExtension": "597", "isMain": true], "SJ" : ["phoneExtension": "47", "isMain": true], "SZ" : ["phoneExtension": "268", "isMain": true], "SE" : ["phoneExtension": "46", "isMain": true], "CH" : ["phoneExtension": "41", "isMain": true], "SY" : ["phoneExtension": "963", "isMain": true], "TW" : ["phoneExtension": "886", "isMain": true], "TJ" : ["phoneExtension": "992", "isMain": true], "TZ" : ["phoneExtension": "255", "isMain": true], "TH" : ["phoneExtension": "66", "isMain": true], "TG": ["phoneExtension": "228", "isMain": true], "TK" : ["phoneExtension": "690", "isMain": true], "TO" : ["phoneExtension": "676", "isMain": true], "TT" :["phoneExtension": "1", "isMain": false], "TN" : ["phoneExtension": "216", "isMain": true], "TR" : ["phoneExtension": "90", "isMain": true], "TM" : ["phoneExtension": "993", "isMain": true], "TC" : ["phoneExtension": "1", "isMain": false], "TV" : ["phoneExtension": "688", "isMain": true], "VI" : ["phoneExtension": "1", "isMain": false], "UG" : ["phoneExtension": "256", "isMain": true], "UA" : ["phoneExtension": "380", "isMain": true], "AE": ["phoneExtension": "971", "isMain": true], "GB" : ["phoneExtension": "44", "isMain": true], "US" : ["phoneExtension": "1", "isMain": true], "UY" : ["phoneExtension": "598", "isMain": true], "UZ" : ["phoneExtension": "998", "isMain": true], "VU" : ["phoneExtension": "678", "isMain": true], "VA" : ["phoneExtension": "379", "isMain": true], "VE" : ["phoneExtension": "58", "isMain": true], "VN" : ["phoneExtension": "84", "isMain": true], "WF" : ["phoneExtension": "681", "isMain": true], "EH" : ["phoneExtension": "212", "isMain": true], "YE" : ["phoneExtension": "967", "isMain": true], "ZM" : ["phoneExtension": "260", "isMain": true], "ZW" : ["phoneExtension": "263", "isMain": true]]
}
public class Country {
public var name: String
public var phoneExtension: String?
public var countryCode: String
public var isMain: Bool?
public init(name: String, phoneExtension: String?, countryCode: String, isMain: Bool?) {
self.name = name
self.phoneExtension = phoneExtension
self.countryCode = countryCode
self.isMain = isMain
}
}
Here's a complete list. Others had missing codes
static let countryPrefixes: [String: String] = ["AF": "93",
"AL": "355",
"DZ": "213",
"AS": "1",
"AD": "376",
"AO": "244",
"AI": "1", "AQ": "672",
"AG": "1",
"AR": "54",
"AM": "374",
"AW": "297",
"AU": "61",
"AT": "43",
"AZ": "994",
"BS": "1",
"BH": "973",
"BD": "880",
"BB": "1",
"BY": "375",
"BE": "32",
"BZ": "501",
"BJ": "229",
"BM": "1",
"BT": "975",
"BA": "387",
"BW": "267",
"BR": "55",
"IO": "246",
"BG": "359",
"BF": "226",
"BI": "257",
"KH": "855",
"CM": "237",
"CA": "1",
"CV": "238",
"KY": "345",
"CF": "236",
"TD": "235",
"CL": "56",
"CN": "86",
"CX": "61",
"CO": "57",
"KM": "269",
"CG": "242",
"CK": "682",
"CR": "506",
"HR": "385",
"CU": "53",
"CY": "537",
"CZ": "420",
"DK": "45",
"DJ": "253",
"DM": "1",
"DO": "1",
"EC": "593",
"EG": "20",
"SV": "503",
"GQ": "240",
"ER": "291",
"EE": "372",
"ET": "251",
"FO": "298",
"FJ": "679",
"FI": "358",
"FR": "33",
"GF": "594",
"PF": "689",
"GA": "241",
"GM": "220",
"GE": "995",
"DE": "49",
"GH": "233",
"GI": "350",
"GR": "30",
"GL": "299",
"GD": "1",
"GP": "590",
"GU": "1",
"GT": "502",
"GN": "224",
"GW": "245",
"GY": "595",
"HT": "509",
"HN": "504",
"HU": "36",
"IS": "354",
"IN": "91",
"ID": "62",
"IQ": "964",
"IE": "353",
"IL": "972",
"IT": "39",
"JM": "1",
"JP": "81",
"JO": "962",
"KZ": "77",
"KE": "254",
"KI": "686",
"KW": "965",
"KG": "996",
"LV": "371",
"LB": "961",
"LS": "266",
"LR": "231",
"LI": "423",
"LT": "370",
"LU": "352",
"MG": "261",
"MW": "265",
"MY": "60",
"MV": "960",
"ML": "223",
"MT": "356",
"MH": "692",
"MQ": "596",
"MR": "222",
"MU": "230",
"YT": "262",
"MX": "52",
"MC": "377",
"MN": "976",
"ME": "382",
"MS": "1",
"MA": "212",
"MM": "95",
"NA": "264",
"NR": "674",
"NP": "977",
"NL": "31",
"AN": "599",
"NC": "687",
"NZ": "64",
"NI": "505",
"NE": "227",
"NG": "234",
"NU": "683",
"NF": "672",
"MP": "1",
"NO": "47",
"OM": "968",
"PK": "92",
"PW": "680",
"PA": "507",
"PG": "675",
"PY": "595",
"PE": "51",
"PH": "63",
"PL": "48",
"PT": "351",
"PR": "1",
"QA": "974",
"RO": "40",
"RW": "250",
"WS": "685",
"SM": "378",
"SA": "966",
"SN": "221",
"RS": "381",
"SC": "248",
"SL": "232",
"SG": "65",
"SK": "421",
"SI": "386",
"SB": "677",
"ZA": "27",
"GS": "500",
"ES": "34",
"LK": "94",
"SD": "249",
"SR": "597",
"SZ": "268",
"SE": "46",
"CH": "41",
"TJ": "992",
"TH": "66",
"TG": "228",
"TK": "690",
"TO": "676",
"TT": "1",
"TN": "216",
"TR": "90",
"TM": "993",
"TC": "1",
"TV": "688",
"UG": "256",
"UA": "380",
"AE": "971",
"GB": "44",
"US": "1",
"UY": "598",
"UZ": "998",
"VU": "678",
"WF": "681",
"YE": "967",
"ZM": "260",
"ZW": "263",
"BO": "591",
"BN": "673",
"CC": "61",
"CD": "243",
"CI": "225",
"FK": "500",
"GG": "44",
"VA": "379",
"HK": "852",
"IR": "98",
"IM": "44",
"JE": "44",
"KP": "850",
"KR": "82",
"LA": "856",
"LY": "218",
"MO": "853",
"MK": "389",
"FM": "691",
"MD": "373",
"MZ": "258",
"PS": "970",
"PN": "872",
"RE": "262",
"RU": "7",
"BL": "590",
"SH": "290",
"KN": "1",
"LC": "1",
"MF": "590",
"PM": "508",
"VC": "1",
"ST": "239",
"SO": "252",
"SJ": "47",
"SY": "963",
"TW": "886",
"TZ": "255",
"TL": "670",
"VE": "58",
"VN": "84",
"VG": "284",
"VI": "340", "EH": "121"]
As far as I am aware, there is no built in method for getting this information. However, you could store the data in your application and look it up based on the country code you just obtained.
A full list of known codes is on Wikipedia
You could store them as a long .plist file, which you can then load in and query as a dictionary keyed by the country code.
let phoneUtil = NBPhoneNumberUtil()
if let countryCode = (Locale.current as NSLocale).object(forKey: .countryCode) as? String {
}
let device = Locale.current.regionCode
do {
let phoneNumber: NBPhoneNumber = try phoneUtil.parse(withPhoneCarrierRegion:phone_txt.text)
let code:String = try phoneUtil.format(phoneNumber, numberFormat: .E164)
let national:String = try phoneUtil.format(phoneNumber, numberFormat: .NATIONAL)
let international:String = try phoneUtil.format(phoneNumber, numberFormat: .INTERNATIONAL)
countryname_lbl.text = phoneUtil.getRegionCode(forCountryCode:phoneNumber.countryCode)!
let numberrr = phoneUtil.getNationalSignificantNumber(phoneNumber)
print("number::",numberrr)
let valid = phoneUtil.isValidNumber(phoneNumber)
print("valid:",valid)
code_lbl.text = code
number_lbl.text = international
national_lbl.text = national
}
catch let error as NSError {
print(error.localizedDescription)
}
}
Download file country_dial_info and add to project
https://gist.github.com/xxcombat/b1cef4a501c7ae358720cd192da3ed48
Download file and add to project
https://gist.github.com/xxcombat/fe08f22b5ecbb629b6900aba9abfd0aa
Example
let regionCode = Locale.current.regionCode
print(regionCode) // "UA"
let phoneCodes: [DialCodeInfo]
let dialCodes = DialCodes()
phoneCodes = dialCodes.databaseCodes ?? []
let myPhoneCode = databaseCodes?.first(where: { info in
info.code == regionCode
})
print(myPhoneCode)
// DialCodeInfo(name: "Ukraine", flag: "🇺🇦", code: "UA", dialcode: "+380"))

Calling Module Function From Model Rails

I'm getting a method or variable not defined when trying to use an array defined in a function in a module.
Here are the files:
/lib/states.rb
module States
def fifty_states
[
'AL',
'AK',
'AZ',
'AR',
'CA',
'CO',
'CT',
'DE',
'FL',
'GA',
'HI',
'ID',
'IL',
'IN',
'IA',
'KS',
'KY',
'LA',
'ME',
'MD',
'MA',
'MI',
'MN',
'MS',
'MO',
'MT',
'NE',
'NV',
'NH',
'NJ',
'NM',
'NY',
'NC',
'ND',
'OH',
'OK',
'OR',
'PA',
'RI',
'SC',
'SD',
'TN',
'TX',
'UT',
'VT',
'VA',
'WA',
'WV',
'WI',
'WY'
]
end
end
/app/controller/player_to_team_histories_controller.rb
class PlayerToTeamHistory < ActiveRecord::Base
include States
def self.distinct_states
joins(:player).select("DISTINCT players.HometownState").where("players.HometownState IN (?)", fifty_states)
end
If I open a console I can do this just fine:
>> include States
Object
>> fifty_states
["AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY"]
I think you're confusing class with instance here. If you want to call fifty_states from inside a class method (i.e. self.distinct_states), then you'll have to use extend, not include:
module A
def foo
"myfoo"
end
end
class B
extend A
def self.bar
foo
end
end
B.bar
#=> "myfoo"
Note however that you then cannot call the method from an instance:
b = B.new
b.bar
#=> NoMethodError: undefined method `bar' for #<B:0x007fefc4e19db0>
Here's an article with more discussion on include vs extend.
The message at the end sums things up well:
Use include for instance methods and extend for class methods. Also, it is sometimes ok to use include to add both instance and class methods. Both are really handy and allow for a great amount of code reuse. They also allow you to avoid deep inheritance, and instead just modularize code and include it where needed, which is much more the ruby way.

Resources