There are many of frameworks out there like PhoneGap that allow you to write iOS apps using HTML and Javascript. Even if you know Objective-C and/or SWIFT, sometimes a UIWebView might be useful. But what if you need to use functionality that’s not available on webkit? Creating a bridge between Javascript and Objective-C is easier than you think!

Open Xcode and create a new project.

Screen Shot 2015-05-23 at 5.16.03 AM

Screen Shot 2015-05-23 at 5.16.14 AM

Open the main storyboard and drag and drop a UIWebView to the main view. Then control + click the UIWebView and set the delegate to the view controller.

Screen Shot 2015-05-23 at 5.17.28 AM

 

Now let’s create a HTML file to load on our UIWebView. I will explain how to write the Javascript functions later.

Screen Shot 2015-05-23 at 5.24.01 AM

 

Since one of the functions is supposed to vibrate the phone, add the AudioToolbox framework to the project. This is not needed to create the bridge. That’s just for vibrating the phone.

Screen Shot 2015-05-23 at 5.55.05 AM

 

Now here’s the secret. All we need to create a bridge is the following delegate method:

– (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

Whenever UIWebView is about to load something, it calls that method first. If it returns true, then it handles the request. What we have to do is to parse the URL and see if the calls are regular URL requests(in that case we must return true) or if they’re our javascript calls. In case they’re our JS calls, we parse the URL and then do something.

//Convert the URL to a NSString
NSURL *URL = [request URL];
NSString *string = [URL absoluteString];

//Check if it’s a message
if([string hasPrefix:@”message:”]){
//Remove the “message:” prefix from the string
string = [string stringByReplacingOccurrencesOfString:@”message:” withString:@””];

//Separate the title from the message
NSArray *components = [string componentsSeparatedByString:@”:title:”];

//Get the title and the message
NSString *title = [components objectAtIndex:1];
NSString *message = [components objectAtIndex:0];

//URLs are always percent encoded, so we have to decode them(e.g. convert %20 into spaces)
title = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)title, CFSTR(“”), kCFStringEncodingUTF8);
message = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)message, CFSTR(“”), kCFStringEncodingUTF8);

//Create the alert view
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil];

//Display show it
[alert show];

//Let the webview know we don’t want it to load the request
return false;
}
//Check if it’s a vibration
else if([string hasPrefix:@”virate:”]){
//Vibrate
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);

//Let the webview know we don’t want it to load the request
return false;
}
//Check if the app wants to open a URL in Safari
else if([string hasPrefix:@”openinsafari:”]){
//Remove the prefix
string = [string stringByReplacingOccurrencesOfString:@”openinsafari:” withString:@””];

//Create the URL
NSURL *aURL = [NSURL URLWithString:string];

//Open in Safari
[[UIApplication sharedApplication] openURL:aURL];

//Let the webview know we don’t want it to load the request
return false;
}

//It’s a regular URL, so let the webview handle it
return true;

To download the sample project, click here. That’s all folks! 😉