Phone number validation and formatting on iOS - ios

I am using this library https://github.com/me2day/libPhoneNumber-iOS for validating the phone numbers.
I want to ask is that on whatsapp If you enter a phone number digits greater or less than the original Phone number of some country it shows error and give you a message that the digits are less than or greater than. How can I do this? how can I figure out the number of digits in phone number used in particular country and gives error according to that.
At the moment I am validating the phone number of country like this
let phoneUtil = NBPhoneNumberUtil.sharedInstance()
do {
let number:NBPhoneNumber = try phoneUtil.parse(phoneNumber, defaultRegion:countryCode)
let isValidNumber: Bool = phoneUtil.isValidNumberForRegion(number, regionCode: countryCode)
return isValidNumber
}catch let error as NSError {
print(error.localizedDescription)
return false
}

Related

How do I differentiate between two countries with the same country code using libPhoneNumber-iOS?

I am using libPhoneNumber-iOS (https://github.com/iziz/libPhoneNumber-iOS) to parse international phone numbers, and I am having a bit of trouble differentiating between different countries with the same country code (e.g. USA and Canada both use +1). Does anyone know if this library does this?
Here is the code I'm using to retrieve the country code (region code i.e. "US"):
let fullPhoneNumber = "+15065552222"
guard let phoneUtil = NBPhoneNumberUtil.sharedInstance() else {
return "error"
}
do {
let phoneNumber = try phoneUtil.parse(fullPhoneNumber, defaultRegion: "ZZ")
return phoneUtil.getRegionCode(forCountryCode: phoneNumber.countryCode)
} catch {
return "error"
}
This code returns "US" for the country code, even though it is a Canadian number. Does anyone know what I can do to get the accurate country using this library?

String to int conversion not working swift

I am trying to do some operation on an array of digits. i wish to combine them and do something. i know reduce operation also works but i am not sure why this is not working.
var digits = [7,2,8,5,0,9,1,2,9,5,3,6,6,7,3,2,8,4,3,7]
var strDigits = ""
for i in digits
{
strDigits += String(i)
}
print(strDigits)
if let number = Int(strDigits) {
print(number)
}
else{
print("didnt work")
}
this will print didnt work. if i reduce the elements in array by 1 it starts working again and print the number. why is the limitation that string cant be cast to int if the string is too long?
When you concat all the numbers to string, the number then becomes too big for Int64 too handle, whose upper limit is 9223372036854775807, whereas your number is 72850912953667328447.
Edited for Martin's correction.

How to determine region from the phone number string?

I tried using PhoneNumberKit and couldn't find any proper api which would give me the region name.
I need the region from the phone number so that I can display the appropriate flag. For example using this:
let phoneNumber = try phoneNumberKit.parse("+12563335956")
let regionCode = phoneNumberKit.countries(withCode: phoneNumber.countryCode)?.first
print("region code is: " , regionCode)
// US phone number with +1 prefix, but it prints "AG" which is wrong.
As you said, the country code can tell you which flag to use.
let phoneNumber = try phoneNumberKit.parse("+1 970162651778")
let regionCode = phoneNumberKit.getRegionCode(of: phoneNumber)
print(regionCode) // Optional("US")
You can get the country region code using the country code of the phone number.

Write Custom Validation for Multiple Fields using MVC

I have a customer form having phone number fields like CountryCode, AreaCode and PhoneNumber. I would like to write a custom validation for these 3 fields where all of them can either remain empty (they are optional) or all of them can remain filled (no field can be left empty if one or two are filled).
Am trying to write a custom validation for this situation, however, am not clear how to do it. Please help.
It's unclear exactly what you're looking for here. If you're just struggling with the boolean logic, all you need is:
if (!String.IsNullOrWhiteSpace(model.CountryCode) ||
!String.IsNullOrWhiteSpace(model.AreaCode) ||
!String.IsNullOrWhiteSpace(model.PhoneNumber))
{
if (String.IsNullOrWhiteSpace(model.CountryCode)
{
ModelState.AddModelError(nameof(model.CountryCode), "Country code is required.");
}
if (String.IsNullOrWhiteSpace(model.AreaCode)
{
ModelState.AddModelError(nameof(model.AreaCode), "Area code is required.");
}
if (String.IsNullOrWhiteSpace(model.PhoneNumber)
{
ModelState.AddModelError(nameof(model.PhoneNumber), "Phone number is required.");
}
}
Essentially, you just first check to see if any of them have a value. Then, you individually add an error for each one that does not have a value.
That said, these broken out phone number fields are atrocious. I'm not sure where the idea came from, but it's like you just can't get people off of them now. Phone number formats vary wildly, and not every phone number actually has an "area code". It's far better to have a single "phone" field where the user can simply type their entire phone number. Then, you can use something like this port of Google's libphonenumber library to validate the number and format it into a standard form. You can even use the library to parse out the individual pieces of country code, area code, and number, if you need to store it like this. Just be prepared that the area code may not have a value and even if it does, it may not be exactly 3 digits. Same goes for number portion, as well: you can't assume it will always be 7.
Validate a phone number
var phoneUtil = PhoneNumberUtil.GetInstance();
try {
var phoneNumber = phoneUtil.Parse(model.Phone, countryISO2);
if (!phoneUtil.IsValidNumber(phoneNumber))
{
ModelState.AddModelError(nameof(model.Phone), "Invalid phone number.");
}
} catch (NumberParseException) {
ModelState.AddModelError(nameof(model.Phone), "Invalid phone number.");
}
Where countryISO2 is the two character country code: "US", "GB", etc. If you want to accept international phone numbers, you should collect the country from the user.
Format a phone number
phoneUtil.Format(phoneNumber, PhoneNumberFormat.NATIONAL);
Get component parts of a phone number
var countryCode = phoneNumber.CountryCode;
string areaCode;
string number;
var nationalSignificantNumber = phoneUtil.GetNationalSignificantNumber(phoneNumber);
var areaCodeLength = phoneUtil.GetLengthOfGeographicalAreaCode(phoneNumber);
if (areaCodeLength > 0) {
areaCode = nationalSignificantNumber.Substring(0, areaCodeLength);
number = nationalSignificantNumber.Substring(areaCodeLength);
} else {
areaCode = "";
number = nationalSignificantNumber;
}

Can I use iOS9 Contacts Framework to get a formatted phone number?

I would like to be able to store a phone number in a standard way, e.g. just the digits (potentially with the '+' for the country code), something like these examples...
"17185555555"
"+17185555555"
"+447788888888"
... but I'd like to be able to DISPLAY it to a user in a properly formatted way, e.g.
"1 (718) 555-5555"
"+1 (718) 555-5555"
"+44 (7788) 888888"
...WITHOUT having to rely on a CNContactViewController to format it.
Obviously doing this just for US/Canada numbers would be easy - it's just one standard format - but I'd like it to be generic so it can work for numbers from any country. I know this question gives an answer for US/Can numbers only.
I know that I could use a CNContactViewController to display the number in the correct format, e.g.
let newContact = CNMutableContact()
newContact.givenName = "John"
newContact.familyName = "Smith"
newContact.phoneNumbers = [CNLabeledValue(label: CNLabelPhoneNumberiPhone, value: CNPhoneNumber(stringValue:"17185555555"))]
let contactView = CNContactViewController(forContact: newContact)
self.presentViewController(contactView, animated: true, completion: nil)
This will show the number on screen properly formatted, i.e.
1 (718) 555-5555
... so I know that something in the framework can do it. (This approach works for other country phone number formats, as long as you prefix the number with the right country code - e.g. "+44...")
From various other questions I know that I can get the raw digits and country code out of a CNContact, e.g. (following above example)
for pNumber: CNLabeledValue in newContact.phoneNumbers {
let value = pNumber.value as! CNPhoneNumber
let cc = value.valueForKey("countryCode") as? String
let digits = value.valueForKey("digits") as? String
print("cc:" + cc + ", " + digits)
}
... but this will just show the unformatted string again - not what I am looking for in this case.
Any help or other recommended approaches really appreciated!
My answer proposes another lib
You can format your numbers with this lib.
And you can use like this:
let phoneNumber: NBPhoneNumber = try phoneUtil.parse("17185555555", defaultRegion: yourRegion)
let formattedString: String = try phoneUtil.format(phoneNumber, numberFormat: .E164)

Resources