UIWebView has very few instance methods. One of them is stringByEvaluatingJavaScriptFromString, which very powerful and unfortunately poorly documented. (This is literally the extent of Apple’s explanation: “Returns the result of running a script.”)
Let’s explore this mysterious method with a couple of examples.
A trivial example of how to use stringByEvaluatingJavaScriptFromString is to get the title of the HTML document:
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
You would typically place this line of code in webViewDidFinishLoad.
This technique is not limited to one-liners, or accessing simple properties. Here’s an example of two lines of JavaScript code executed in order, as you would expect:
[webView stringByEvaluatingJavaScriptFromString:@"var field = document.getElementById('field_2');" "field.value='Multiple statements - OK';"];
You can also call JavaScript functions this way. And if you want to call a JavaScript function that does not already exist in the web page that you’re downloading, you can “inject” it yourself with this technique:
[webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');" "script.type = 'text/javascript';" "script.text = \"function myFunction() { " "var field = document.getElementById('field_3');" "field.value='Calling function - OK';" "}\";" "document.getElementsByTagName('head')[0].appendChild(script);"]; [webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];
In essence I’m using Objective C to create a string which represents JavaScript which which when executed adds a JavaScript function to the HTML DOM. Apologies for the multiple meta levels… Let me try to untangle this line by line.
Line 1 : First we create a <script> element using JavaScript.
Line 2 : Set the type of the <script> element to text/javascript.
Line 3-6 : Set the content of the <script> element to the JavaScript function that you want to inject.
Line 7 : Add the new <script> element as a child to the <head> element of the HTML DOM.
Line 9 : Call the new JavaScript function.
Bonus tip: You can break up NSString constants over multiple lines in Xcode for increased readability. Just end the line with a double-quote character and begin the next line with a double-quote character. At compile time these lines will be joined into one string. So the string that begins with “var script” on Line 1 is one continuous string ending with “appendChild(script);” on Line 7.
Although it’s not critical for the discussion above, here’s the HTML that the example JavaScript refers to:
<html> <head> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0"/> </head> <body> <p>This is the UIWebView</p> <form> <input id="field_1" type="text" name="value" /><br/> <input id="field_2" type="text" name="value" /><br/> <input id="field_3" type="text" name="value" /><br/> </form> </body> </html>
You can use this generic technique to add JavaScript to any web page that you’re downloading and displaying in a UIWebView. The technique and the possibilities are similar to what you can do with the Greasemonkey plugin for Firefox.