Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS JS Class Object injection into WebView

I'm trying to inject JS into UIWebView. Until some point, everything worked like charm:


In viewDidLoad I loaded a HTML button to WebView:

NSString *loadedHTML = <input type='button' onclick='test();' value='test'/>;
[_webView loadHTMLString:loadedHTML baseURL:nil];

so I could test whether my JS function works by just clicking the button. In webViewDidFinishLoad:webView I was injecting a JS function:

NSString *jsScript = 
@"var test = function() {alert('not in class')};"
@"document.getElementsByTagName('head')[0].appendChild(test);";

[webView stringByEvaluatingJavaScriptFromString:jsScript];

This works perfectly.


Now I need to create a similar function, but it has to be inside an object. What I tried is:

changing HTML, so the button calls an object function:

loadedHTML = <input type='button' onclick='myObject.test();' value='test'/>;

changing JS, so it creates an object and a function in it:

jsScript = 
@"var myObject = new function() {"
@"var test = function() {alert('not in class')};"
@"document.getElementsByTagName('head')[0].appendChild(myObject);";
@"}";

It does nothing. I've tried to create the object in three different ways, append myObject.test to document - nothing helped. What do I do wrong here?

like image 871
Mateusz Avatar asked Apr 15 '14 16:04

Mateusz


2 Answers

What happened to work, is to create a JS object like that:

var myObject = {
   test: function() {alert('in class!')}
}

Then, calling a myObject.test() function works.

like image 108
Mateusz Avatar answered Oct 16 '22 00:10

Mateusz


Here's some code that works for me:

NSString *jsScript =
@"var script = document.createElement('script');"
@"    script.type = 'text/javascript';"
@"    script.text = '"
@"        var myObject = (function() {"
@"            return {"
@"                test: function() {"
@"                    alert(\"foo\");"
@"                }"
@"            }"
@"        })();"
@"';"
@"document.getElementsByTagName('head')[0].appendChild(script);";

NSString *result = [self.webMain stringByEvaluatingJavaScriptFromString:jsScript];

The difference (primarily) is creating the script element to add to the DOM. I made a minor change to the JS code itself using a style that I prefer for objects with methods.

One recommendation I would make in general, though, is to load Javascript files from resources. If this would work for you, it's much simpler to read and debug Javascript from separate files rather than write it with all the messy quoting that happens when you embed it inline in Objective-C.

like image 2
Blake Schwendiman Avatar answered Oct 16 '22 02:10

Blake Schwendiman