Introduction
I am a founder at a startup that needs a way to format and work with mobile phone numbers on the iPhone. For a while, I was searching for a library that would help me and found, like many others, Google's libphonenumber
.
The problem is that the library has no ready made variant for the iPhone, so I was faced with 2 choices, taking the validation code to the server side or trying to compile the C++ variant of the library for iPhone.
I wasn't pleased with either, and then I thought about the JavaScript implementation of the library and decided to use that.
Adding the JavaScript variant of the libphonenumber
library to an iPhone app is easy, but there are some problems with that:
libiphonenumber
is dependent heavily on the closure library so you have to add that also to your project or let the UIWebview
control download all of the js files that he needs, this of course implies that you can only use it when you are online ! - The performance of using the JavaScript variant of the library are very poor because there are many sparsed js files and the scripts are long and not optimized.
Now the internet is filled with half solutions and dead end 10 line answers, but I am going to show you how to compile and use libphonenumber
in your iPhone apps in an efficient and compact way.
Background
I demonstrate the use of the library by implementing a JavaScript method by the name of buildAndValidatePhone
which validates a mobile phone number taking his country code into consideration and returning his international format or the string
"invalid
" in case of error.
You should add methods to the JavaScript side and call them from your app side as I demonstrate, read the libphonenumber
documentation it is a powerful library.
Using the Code
What I've done is to create an hidden UIWebview
control in my app that is loading a compiled JavaScript file.
The JavaScript file calls the libphonenumber
JavaScript implementation but it is a squeezed file with all of the dependencies, like the closure library, that libphonenumber
needs.
The app invokes JavaScript calls, in our example we call the method buildAndValidatePhone
, and get's the results that it needs, in the example below, I will show you how to call a method that will check if a mobile phone number is valid, and you can take it off from there.
Ok, enough talking, let's cut to the chase.
- First, let's examine the JavaScript file itself and what to do with it:
goog.require('goog.dom');
goog.require('goog.json');
goog.require('goog.proto2.ObjectSerializer');
goog.require('goog.array');
goog.require('goog.proto2.PbLiteSerializer');
goog.require('goog.string');
goog.require('goog.proto2.Message');
goog.require('goog.string.StringBuffer');
goog.require('i18n.phonenumbers.NumberFormat');
goog.require('i18n.phonenumbers.PhoneNumber');
goog.require('i18n.phonenumbers.PhoneNumberUtil');
function buildAndValidatePhone(phoneNumber, countryCode) {
var strIntlNumber = "invalid";
try {
var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
var regionCode = phoneUtil.getRegionCodeForCountryCode(countryCode);
var number = phoneUtil.parseAndKeepRawInput(phoneNumber, regionCode);
if (phoneUtil.isValidNumber(number)) {
var PNT = i18n.phonenumbers.PhoneNumberType;
var numberType = phoneUtil.getNumberType(number);
if (numberType == PNT.MOBILE) {
var PNF = i18n.phonenumbers.PhoneNumberFormat;
strIntlNumber = phoneUtil.format(number, PNF.E164);
strIntlNumber = strIntlNumber.replace('+','');
}
}
}
catch(ex) {
}
return strIntlNumber;
};
You should copy the content of the file and paste it in the closure compiler page:
Just copy/paste the JavaScript above instead of the text in the editor of the compiler and press build.
The compiler will find all of the references that libphonenumber
is having with the closure library and create one squeezed JavaScript file.
- Download the JavaScript file to your local disk and change its extension from js to txt, this is crucial because XCode doesn't like js files, it treats them like source code and not like resource files.
In our example, I have called it: libphonenumber.txt
, Drag the file into XCode and add it to the project.
- Use the code snippet below to load the JavaScript file into a
UIWebView
and call our JavaScript method, something like this:
UIWebView *_webView = [[UIWebView alloc] init];
_webView.delegate = self;
NSString *htmlString = [NSString stringWithString:@"<html>
<script type='text/javascript' src='libphonenumber.txt'></script></html>"];
[_webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:
[[NSBundle mainBundle] resourcePath]]];
- Make sure you implement
UIWebViewDelegate webViewDidFinishLoad
and use the code snippet below to call our JavaScript method from objective C:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *mobileNumber = @"0541234567";
int countryCode = 972;
NSString *formattedCall = [NSString stringWithFormat:
@"buildAndValidatePhone('%@', %d);", mobileNumber, countryCode];
NSString *formattedNumber =[_webView stringByEvaluatingJavaScriptFromString:formattedCall];
NSLog(@"result: %@", formattedNumber);
}
I am always amazed at how hours and hours of work translated to half a page of code at the end.
I hope this tip will be of an interest to someone, I'm sure it will...
Enjoy!