简体   繁体   English

使用Objective-C进行JavaScript注入的方法

[英]Methods of JavaScript injection using Objective-C

I'm looking for different methods of injecting JavaScript into a WebView (in Cocoa). 我正在寻找将JavaScript注入WebView(在Cocoa中)的不同方法。

I am trying to inject some javascript into the <head> tag of a HTML file that has been loaded into the WebView. 我试图将一些javascript注入已加载到WebView的HTML文件的<head>标记中。

The following method doesn't work for me. 以下方法对我不起作用。 It seems to only work with very simple JavaScript with no nested brackets (from what I have tested): 它似乎只适用于非常简单的JavaScript, 没有嵌套括号 (来自我测试的):

[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"var script = document.createElement('script');"
                                                     "script.type = 'text/javascript';"
                                                     "script.text = \"some simple JavaScript"
                                                     "}\";"
                                                     "document.getElementsByTagName('head')[0].appendChild(script);"]];

Are there any other ways of doing this with more complicated JavaScript / jQuery functions? 有没有其他方法可以使用更复杂的JavaScript / jQuery函数?

The full code I am trying to inject is as follows: 我试图注入的完整代码如下:

function submitFormForTime(time){
    $(\".t_h\").each(function(i, obj) {
        if ($(this).text() != time) return;
        $(this).parent().find(\"form\").each(function(i, obj){
            obj.submit();
        });
    });
}

You can't use jQuery to add <script> tags. 您不能使用jQuery添加<script>标记。 This has been asked many times. 这已被问过很多次了。 See: 看到:

You can do it with browser built-in functions, BUT: 您可以使用浏览器内置函数来执行此操作,但是:

Would it work to just assign your function to a variable on your page and then evaluate it? 是否可以将您的函数分配给页面上的变量然后进行评估? Something like: 就像是:

-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    // add function to page:
    NSString * js = @"myFunction = function(){ return \"success!\"; }" ;
    [ webView stringByEvaluatingJavaScriptFromString:js ] ;

    // execute newly added function:
    NSString * result = [ webView stringByEvaluatingJavaScriptFromString:@"myFunction();"] ;
    NSLog(@"result=\"%@\"", result) ;
}

update explicit examples: 更新显式示例:

You should use my above example as a template! 你应该使用我上面的例子作为模板!

Anyway, there's 2 parts to the process... The Javascript part and the Objective-C part. 无论如何,这个过程分为两部分...... Javascript部分和Objective-C部分。 At the Javascript level, you are doing this: 在Javascript级别,您正在执行此操作:

// assign a function to the variable "someFunction":
var someFunction = function(){...};

// call the function in the variable "someFunction":
someFunction();

You can also do it without assigning the function to a variable, for example, if you don't care about referring to the function in the future. 您也可以在不将函数分配给变量的情况下执行此操作,例如,如果您不关心将来引用该函数。 Doing it without a variable and using an anonymous function looks like this: 在没有变量和使用匿名函数的情况下执行此操作如下所示:

( function(){...} )() ;

ie instead of doing var A = <the function>; A(); 即代替做var A = <the function>; A(); var A = <the function>; A(); you are doing (<the function>)(); 你在做什么(<the function>)();

Finally, if your anonymous function takes arguments, like yours does, the pattern looks like this: 最后,如果您的匿名函数接受参数,就像您的那样,模式如下所示:

( function(var0, ..., varN){...} )(arg0, ..., argN);

Using that as a template for your code, your JS ends up like: 使用它作为代码的模板,你的JS最终会像:

( function(time) {
    $(\".t_h\").each(function(i, obj) 
    {
        if ($(this).text() != time)  return;

        $(this).parent().find(\"form\").each(function(i, obj) {
            obj.submit();
        });
    });
})( 123.456 );

So, that's what you want the web view to execute... That's the code we pass to the webview. 所以,这就是你希望web视图执行的内容......这就是我们传递给webview的代码。 But you have to build that string in your Obj-C program, with the "complication" of inserting the current time argument ( 123.456 in the above code). 但是你必须在你的Obj-C程序中构建该字符串,并且插入当前时间参数的“复杂性”(上面的代码中为123.456 )。

It looks like this: 它看起来像这样:

NSString * jsTemplate =
    @"( function(time) {"
    @"        $(\".t_h\").each(function(i, obj) {"
    @"            if ($(this).text() != time)  return;"
    @"            $(this).parent().find(\"form\").each(function(i, obj) {"
    @"                obj.submit();"
    @"            });"
    @"        });"
    @"    })( %g );" ;
NSString * js = [ NSString stringWithFormat:jsTemplate, 123.456 ] ;
NSString * result = [ webView stringByEvaluatingJavaScriptFromString:js ] ;

I think I've written enough now :) 我想我现在已经写得够了:)

I would get all the HTML from web view, then I'd inject the code and reload the page. 我会从Web视图中获取所有HTML,然后我会注入代码并重新加载页面。 It's still not a proper method of injection, but it may work. 它仍然不是一种合适的注射方法,但它可能有效。

NSString *htmlDataString = [webView stringByEvaluatingJavaScriptFromString: @"document.documentElement.outerHTML"];
// use nsstring methds to find the place for injecting
// inject avascript code
[webView loadHTMLString:htmlDataString baseURL:nil];

Of course you may have base URL from your request, if so replace that nil. 当然,您可以从您的请求中获得基本URL,如果是,则替换为nil。

I didn't tried this, but if the problem is with the brackets and the complexity of the code, you can try calling a JS file stored in the bundle. 我没试过这个,但如果问题是括号和代码的复杂性,你可以尝试调用存储在bundle中的JS文件。 Maybe it solves that. 也许它解决了这个问题。 For example: 例如:

NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@”submitFormForTime” ofType:@”js”]];

NSString *jsString = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];

[webView stringByEvaluatingJavaScriptFromString:jsString];

Maybe setting the encoding type helps to parse all the brackets in a right way. 也许设置编码类型有助于以正确的方式解析所有括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM