How to work with native iOS and javascript callbacks in Objective-C

Recently I worked on a small iOS mobile project around Javascript. I wanted to load web content from iOS with Javascript inside and get callbacks from Javascript into iOS, to save native data and transmit it to an other controller if needed. The second part was also to call Javascript methods from iOS part.

UPDATE: If you are interested for a Swift version of this article, I created a new one compatible with Swift and Webkit, Apple’s most optimized web framework: iOS Webkit, Swift and Javascript

Javascript to iOS

This part is pretty easy; we need to add the JavascriptCore framework in our project to get access to the Javascript context. For my part, I’ve added an html file with a form inside. Β When I will click on the submit button, it going to call a javascript function that will follow the params into the iOS part.

Here is my form:

<form class="form-signin" role="form">
    <div class="form-content">
        <label for="email" class="form-email">Already an account?</label>
        <input type="email" id="email" class="form-control" placeholder="Email" required autofocus />
        <input type="password" id="password" class="form-control" placeholder="Password" required>

        <button class="btn btn-lg btn-primary btn-block" type="button" onClick="sendLoginAction()">Submit</button>
    </div>

</form>

Here is my javascript part:

function sendLoginAction() {
    sendObjcLoginAction(document.getElementById("email").value, document.getElementById("password").value);
}

At the end, we need to implement the UIWebViewDelegate protocol to get response of our webview methods. In this way, we can get access to the javascript context and catch the javascript calls.

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    JSContext *context =  [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    context[@"sendObjcLoginAction"] = ^(NSString *email, NSString *password) {
       NSLog(@"GET CALLBACK %@ %@", email, password);
    };
}

So we can catch the email and password params from the web view using javascript. How about calling back a javascript function inside our web view, refreshing an html field or showing an alert.

iOS to Javascript

I’ve just added a small javascript function with a param, to show an alert inside my web view.

function isLogged(success) {
    if (success) {
        alert("Success");
    }
}

And finally, using the javascript context inside the iOS part, we can call our function with arguments

- (void)authenticationSuccess
{
    JSContext *tmpContext =  [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    [tmpContext[@"isLogged"] callWithArguments:@[@true]];
}

And that’s it, pretty simple! So with few lines of code, we can catch javascript events in iOS and call it back if needed.

UPDATE: A new version of this blog post is available for Swift: iOS Webkit, Swift and Javascript

© 2020 Benoit Pasquier. All Rights Reserved
Author's picture

Benoit Pasquier

iOS Software engineer πŸ‡«πŸ‡·, writing about Swift, Data and more.

ShopBack πŸ’°

Singapore πŸ‡ΈπŸ‡¬