How to format phone number realtime (when using UITextfield) in iOS for different region codes?
Asked Answered
C

2

5

I found 'NBAsYouTypeFormatter' and referred to the demo provided. But, I want phone number formatted dynamically when user entering phone number in UITextField.

Remember, region code is not fixed to one or two country in my case e.g. only @"US" or only other. Region code will be selected by user from drop down and selected code will be passed by me by following line:

NBAsYouTypeFormatter *asYouTypeFormatter = [[NBAsYouTypeFormatter alloc] initWithRegionCode:@"US"];  // may be any other than 'US'
NSString *output = [asYouTypeFormatter inputString:@"9999988888"];

Now, how would I be able to format number textfield dynamically when user types in number textfield?

Cornet answered 4/2, 2015 at 6:49 Comment(0)
C
10

Here is how I achieved that. I am going to explain from scratch. So, new users can get the way from scratch.

Download libPhoneNumber-iOS library from here. At the bottom side of the page of that link, you will find what files you need to add to your project.

Your bundle should look like this:

Bundle

Now, follow below steps to implement.

(1) Import files in the view controller where you need your textfield to be formatted.

#import "NBPhoneMetaDataGenerator.h"
#import "NBPhoneNumberUtil.h"
#import "NBAsYouTypeFormatter.h"

and make instance of type NBAsYouTypeFormatter in header file:

NBAsYouTypeFormatter *asYouTypeFormatter;

(2) In the viewDidLoad method of that view controller, initialize that object taken earlier:

asYouTypeFormatter = [[NBAsYouTypeFormatter alloc] initWithRegionCode:@"IN"];

Note: @"IN" is for India. You can set it to anything you want. Refer to plist file that will be included in libPhoneNumber-iOS library to view full list of region codes.

(3) In delegate method of UITextField, dynamically manage text of yout textfield.

#pragma mark
#pragma mark - Phone Number textfield formatting

# define LIMIT 18 // Or whatever you want

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // Just allow 18 digits
    if(!(([string length] + range.location) > LIMIT))
    {
        // Something entered by user
        if(range.length == 0)
        {
            [textNumber setText:[self.asYouTypeFormatter inputDigit:string]];
        }

        // Backspace
        else if(range.length == 1)
        {
            [textNumber setText:[self.asYouTypeFormatter removeLastDigit]];
        }
    }

    return NO;
}

Hope it helps others !!!

Cornet answered 4/2, 2015 at 12:17 Comment(7)
Can you give me the crash report ?Cornet
when i use this code s first time button press so it work well but second time press so crashInsalivate
+ (NBPhoneMetaData *)getMetadataForRegion:(NSString *)regionCode { [NBMetadataHelper initializeHelper]; if ([self hasValue:regionCode] == NO) { return nil; } regionCode = [regionCode uppercaseString]; if ([cachedMetaDataKey isEqualToString:regionCode]) { return cachedMetaData; } This function in if ([cachedMetaDataKey isEqualToString:regionCode]) here get bed access error.Insalivate
I have edited my answer by adding one screenshot, refer to it. Your bundle should look like that. And have you added CoreTelephony.framework ?Cornet
Let us continue this discussion in chat.Cornet
I'm not sure if this problem is directly associated with your implementation of this method, but if the cursor is at the beginning of the text field, it will end up appending the digit to the end.Roulade
A more complete solution is here - https://mcmap.net/q/1922257/-phone-number-format-iosYuonneyup
I
5

In UITextField delegate's method

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *totalString = [NSString stringWithFormat:@"%@%@",textField.text,string];

    if (range.length == 1)
    {
        // Delete button was hit.. so tell the method to delete the last char.
        NSError *error = nil;
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[\\s-\\(\\)]" options:NSRegularExpressionCaseInsensitive error:&error];
        totalString = [regex stringByReplacingMatchesInString:totalString options:0 range:NSMakeRange(0, [totalString length]) withTemplate:@""];
        totalString = [totalString substringToIndex:[totalString length] - 1];
    }

    textField.text = [Utility formatPhoneNumber:totalString countryCode:@"theCountryCode"];

    return NO;
}

This function will format your string to phone format number basing on the provided country code.

+ (NSString *)formatPhoneNumber:(NSString *)simpleNumber countryCode:(NSString *)countryCode
{
    if (simpleNumber.length == 0)
    {
        return @"";
    }

    NSInteger maxLen = 15;

    // use regex to remove non-digits(including spaces) so we are left with just the numbers
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^[0-9+]]" options:NSRegularExpressionCaseInsensitive error:&error];
    simpleNumber = [regex stringByReplacingMatchesInString:simpleNumber options:0 range:NSMakeRange(0, [simpleNumber length]) withTemplate:@""];

    // check if the number is to long
    if (simpleNumber.length > maxLen)
    {
        // remove last extra chars.
        simpleNumber = [simpleNumber substringToIndex:maxLen];
    }

    NSString *firstChar = @"";
    BOOL countryCodeLen = countryCode.length;

    if (simpleNumber.length > 0)
    {
        firstChar = [simpleNumber substringToIndex:1];
    }

    if ([firstChar isEqualToString:@"+"])
    {
        //+1 (234)
        if (simpleNumber.length < 5 + countryCodeLen)
        {
            NSString *string = [NSString stringWithFormat:@"(\\d{%d})(\\d+)",countryCodeLen];
            //            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:@"(\\d{1})(\\d+)"
            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:string
                                                                   withString:@"$1 ($2)"
                                                                      options:NSRegularExpressionSearch
                                                                        range:NSMakeRange(0, [simpleNumber length])];
        }
        //+1 (234) 567
        else if(simpleNumber.length < 8 + countryCodeLen)
        {
            NSString *string = [NSString stringWithFormat:@"(\\d{%d})(\\d{3})(\\d+)",countryCodeLen];
            //            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:@"(\\d{1})(\\d{3})(\\d+)"
            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:string
                                                                   withString:@"$1 ($2) $3"
                                                                      options:NSRegularExpressionSearch
                                                                        range:NSMakeRange(0, [simpleNumber length])];
        }
        //+1 (234) 567-
        else   // else do this one..
        {
            NSString *string = [NSString stringWithFormat:@"(\\d{%d})(\\d{3})(\\d{3})(\\d+)",countryCodeLen];
            //            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:@"(\\d{1})(\\d{3})(\\d{3})(\\d+)"
            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:string
                                                                   withString:@"$1 ($2) $3-$4"
                                                                      options:NSRegularExpressionSearch
                                                                        range:NSMakeRange(0, [simpleNumber length])];
        }
    }
    else
    {
        // 123 456 7890
        // format the number.. if it's less then 7 digits.. then use this regex.
        if (simpleNumber.length < 7)
        {
            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:@"(\\d{3})(\\d+)"
                                                                   withString:@"($1) $2"
                                                                      options:NSRegularExpressionSearch
                                                                        range:NSMakeRange(0, [simpleNumber length])];
        }
        else   // else do this one..
        {
            simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:@"(\\d{3})(\\d{3})(\\d+)"
                                                                   withString:@"($1) $2-$3"
                                                                      options:NSRegularExpressionSearch
                                                                        range:NSMakeRange(0, [simpleNumber length])];
        }
    }

    return simpleNumber;
}

Hope this help

Initiate answered 4/2, 2015 at 7:31 Comment(2)
Thanks @Tai Le Anh. But how will I do it real-time i.e when user is entering number into UiTextField. Conversion is happening already in the code that I have mentioned in my question.Cornet
The solution is for real-time. Worked very well for me.Main

© 2022 - 2024 — McMap. All rights reserved.