iOS - Communication from iOS to JavaScript

iOS - Communication from iOS to JavaScript

This is the first part of a series about communication between iOS and JavaScript. In this part we will see

  1. How to call JavaScript functions from iOS
  2. How to get return value of executed JavaScript functions back to iOS
  3. How to pass variety of objects types (String, object) to JavaScript functions

For convenience, I am going to replace the word iOS with Swift from now on. This is to avoid confusion with similar language, Objective-C used in iOS development

Since we are dealing with iOS, I am assuming all the JavaScript code will be executed in UIWebView. Of course, WKWebView is an another alternative to using UIWebView. But as far as the scope of this article is concerned, I have not touched WKWebView to keep the size of post limited

Swift provides a great and convenient function to call JavaScript functions directly from iOS. To get started, you may first create a sample HTML file with following content. This content contains HTML plus JavaScript which will get loaded on the UIWebView which can then be used by our Swift code

I have also added a demo code for communication between iOS and JavaScript and it is hosted on the GitHub. It demonstrates two way communication. From iOS to JavaScript and other way around, along with minor examples mentioned in this post

web-side code


<html>
<title>
    my title
</title>

<head>
<script>
    function customMessageCreator(name) {
        return 'Hi ' + name + ' It\'s nice to meet you. I hope ' + name + ' has a nice day!'
    }

    function customMessageWithDictionary(nameDetails) {
        var oData = JSON.parse(nameDetails);
        return oData["name"] + " is awesome";
    }

    function invokeMessage() {
        var inputName = document.getElementById('name').value
        triggerWithCustomMessage(inputName)
    }

    </script>
    </head>
<body>
<button onclick='invokeMessage()'>Type and Click</button>
<input type='text' name='firstname' id='name' value='Jamie'><br>
    </body>
</html>

When this code is loaded into your webview, page will look like this,

sample_html_code_demo

  • If you look at above code, you will find two JavaScript functions. viz.
    • customMessageCreator - takes name as an input and returns the custom made string from the input string
    • customMessageWithDictionary - takes a dictionary as an input, extracts the value for given key and returns the value associated with it

Now, let's see how you can use the JavaScript code above to pass standard object types and get values back.

  • Before you go ahead, make sure you set UIWebView object delegate to current class in which it is contained. Next step, make sure you implement a UIWebView delegate method func webViewDidFinishLoad(_ webView: UIWebView). This method will give callback to your controller once web view has finished loading all the content, which also includes JavaScript.

It is important to wait to execute any JavaScript code until web view has finished loading. Otherwise, JavaScript code won't be available to iOS counterpart and it will fail to return any result back

  • Code below demonstrates how we can execute these two functions and get expected values back from JavaScript

// Executing function which simply takes a string is straightforward as demonstrated below.

// value is "Hi jayesh It's nice to meet you. I hope jayesh has a nice day!"
let value = webView.stringByEvaluatingJavaScript(from: "customMessageCreator('jayesh')")

// Executing JavaScript function which takes objects - Array or Dictionaries is little bit difficult since we have to convert Swift dictionary to JSON string and then JavaScript code has to convert this JSON string to JavaScript native object representation

// You can either pass a json string to JavaScript method
let encodedProcessedData = "{\"name\": \"foobar\"}"

// Or you can create the one from Swift dictionary
// input payload
let inputPayload = ["name": "jayesh"]
// Serialize the Swift object into Data
let serializedData = try! JSONSerialization.data(withJSONObject: inputPayload, options: [])
// Encode the data into JSON string
let encodedData = String(data: serializedData, encoding: String.Encoding.utf8)
// Now pass this dictionary to javascript function (Assuming it exists in the HTML code)
let resultValue = webView.stringByEvaluatingJavaScript(from: "customMessageWithDictionary('\(encodedData!)')")

I have mentioned the JavaScript code above, but for the sake of completeness, let's go over it one more time.


// JavaScript function which takes Swift dictionary as an input in the form of JSON string
function customMessageWithDictionary(nameDetails) {
// Parse the JSON string into JavaScript object
    var parsedJSONObject = JSON.parse(nameDetails);
// Extract the name out of parsed JavaScript object and do further processing
    return parsedJSONObject["name"] + " is awesome";
}

That should be it as long as passing parameters or values from Swift to JavaScript is concerned. For the sake of brevity I have avoided writing the same iOS code of Objective-C since it only differs in syntax and few refinements Swift has introduced.

Summary:


In this post we convered how to pass objects from native iOS to JavaScript. This is very useful when you have custom webpage embedded into UIWebView and you want to invoke certain actions on web page based on the state of iOS app. This is not really frequent case, but you can also use this technique to execute functions which are readily accessible in JavaScript but may not be available on iOS platform. These APIs offer excellent interface to communicate iOS message over to JavaScript.

This is the first part of 2 series articles on Communication between JavaScript and iOS. In the next article we will talk about how to communicate to iOS (Swift) from JavaScript functions