Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Native iOS Country Picker

I'm developing an app with an custom Registration Flow, where the user should set his nationality or his home Country.

My question is, if it's possible to get this information via an native ViewController like ABPeoplePickerNavigationController for contacts.

Should look like this (iPhone 6, iOS 8.x, contacts App 'select a Country'):

enter image description here

Thanks

like image 450
KonDeichmann Avatar asked Apr 17 '15 09:04

KonDeichmann


3 Answers

It is very easy to make your own Country Picker.

You can get the country list(country codes) easily from NSLocale,

NSArray *countryArray = [NSLocale ISOCountryCodes];

Also you will get the country name list using displayNameForKey method,

NSLocale *locale = [NSLocale currentLocale];

NSMutableArray *sortedCountryArray = [[NSMutableArray alloc] init];

for (NSString *countryCode in countryArray) {

    NSString *displayNameString = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];

    [sortedCountryArray addObject:displayNameString];
}

[sortedCountryArray sortUsingSelector:@selector(localizedCompare:)];

Just use the sortedCountryArray for populating tableView in your picker class.

like image 177
Anusha Kottiyal Avatar answered Nov 02 '22 19:11

Anusha Kottiyal


I think you have to make your own one using modal view controller.

Alternatively, you can use this one, which works quite well.

like image 45
Jakehao Avatar answered Nov 02 '22 19:11

Jakehao


No there isn't a built-in picker for countries. Same about the classic picture reader, its the stuff you have to make yourself.

Thankfully, it's rather easy to make and find, wether you want someone else's (lockwood is a very realiable programmer, i'm sure his CountryPicker is great).

Or you can go the harder way and make one yourself from scratch.

Note that if you have all the country codes (BE, FR, EN, NL, PT, etc.) you can find the localized name with iOS.

What I did in my code was importing a massive static dictionary of all country codes, and simply use their localized names in the tableview.

This is how I got all the codes (and international prefixes, because my app needs that).

- (NSMutableDictionary*)dialCodeDict{
    NSMutableDictionary *dialCodeDict = [[NSMutableDictionary alloc]initWithObjectsAndKeys:
                                  @"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",
                                  nil];

    return dialCodeDict;
}

And then I did this :

- (void)viewDidLoad {
    _dialCodes = [self dialCodeDict];
    [self setCodes];
}

- (void)setCodes{
    CTTelephonyNetworkInfo *network_Info = [CTTelephonyNetworkInfo new];
    CTCarrier *carrier = network_Info.subscriberCellularProvider;

    NSArray *keys   = [_dialCodes allKeys];
    NSArray *values = [_dialCodes allValues];
    _countries = [[NSMutableArray alloc]initWithCapacity:[_dialCodes count]];

    NSString *baseCountry = [_dialCodes objectForKey:carrier.isoCountryCode.uppercaseString];
    for (int i = 0; i < [_dialCodes count] ; i++){

        Country *c = [[Country alloc]init];

        c.isoC  = [keys objectAtIndex:i];
        c.dialC = [values objectAtIndex:i];
        c.nameC =  [[NSLocale currentLocale] displayNameForKey:NSLocaleCountryCode value:c.isoC];
        c.isLocal = NO;
        if ([baseCountry isEqualToString:[values objectAtIndex:i]]){
            c.isLocal = YES;
            _myCountry = c;
        }

        [_countries addObject:c];

    }

    [_countries sortUsingComparator:^(Country *firstObject, Country *secondObject) {
        return [firstObject.nameC caseInsensitiveCompare:secondObject.nameC];
    }];

    [self.tableView reloadData];
    idx = [NSIndexPath indexPathForRow:[_countries indexOfObject:_myCountry] inSection:0];
    [self.tableView selectRowAtIndexPath:idx animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}

I think there is too much code for what you need but, what this does is fill a tableview of all countries and align the view to the current country (if the user has a sim card or an NSLocale)

This is how i designed the tableview :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *cellIdentifier = @"InternationalCell";
    CustomCellInternationalTableViewCell *cell;

    cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil){
        [tableView registerNib:[UINib nibWithNibName:@"CustomCellInternationalTableViewCell" bundle:nil] forCellReuseIdentifier:cellIdentifier];
        cell = [[CustomCellInternationalTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }else{
        cell.lbCountry.text = [[_countries objectAtIndex:indexPath.row]nameC];
        cell.lbCode.text    = [NSString stringWithFormat:@"+%@",[[_countries objectAtIndex:indexPath.row]dialC]];
        if ([[_countries objectAtIndex:indexPath.row]isLocal] == YES){
            cell.contentView.backgroundColor = FlatGray;
        }else{
            cell.contentView.backgroundColor = ClearColor;
        }
    }

    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [_countries count];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    _myCountry = [_countries objectAtIndex:indexPath.row];
    self.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self dismissViewControllerAnimated:YES completion:nil];
}

Again, there are some lines that i could remove because this is straight from my code, and because it's not well commented (my bad :D) I don't remember which would be important to you and which wouldn't ! But i'll re-read and edit if necessary.

like image 39
Gil Sand Avatar answered Nov 02 '22 17:11

Gil Sand