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.
December 6th, 2009 at 14:44
you can also call a JS file from a bundle (get around that readability snag and have as many fnctions as you need)….
NSString *filePath = [[NSBundle mainBundle] pathForResource:@”loco” ofType:@”js” inDirectory:@”"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSString *jsString = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
[webby stringByEvaluatingJavaScriptFromString:jsString];
December 16th, 2009 at 22:42
Hi, this is my question. How can I change this to only show one image or id or tag? Any help would be great.
December 22nd, 2009 at 23:41
@Nick:Hi, Nick! Do you know how to use javascript to control YouTube player? I want to play a video from YouTube in my iPhone app, but I don’t want the embed preview page. I wonder if I can control the player. Do you know how? Please help me, and thank you in advance!
December 23rd, 2009 at 08:45
@Walker: Unfortunately the JavaScript API for the YouTube player does not work in a UIWebView. We spent a week trying to figure out how to use JavaScript to play a video, to no avail.
December 23rd, 2009 at 19:26
@Nick:Oh! Taht’s too bad. But thank you all the same!