如何在iOS上注入用户脚本?

Mos*_*she 13 browser objective-c uiwebview userscripts ios

我正在研究Fahrii,它本质上是一个支持用户脚本的移动浏览器.目前,我在加载到UIWebView的网页上调用脚本时遇到问题.如果可能的话,我想保留这些公共API.如果没有,概念证明至少会很好,所以我可以更好地理解它是如何工作的.我试图在webViewDidFinishLoad:方法中这样做.

我尝试通过读取webView的内容(使用JavaScript)进行注入,然后将其加载回来loadHTML:baseURL:,但这会导致无限递归.(完成的加载会导致脚本被注入,这反过来导致完成"加载".)

接下来,我尝试过这样的事情:

    [self.browser stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.innerHTML = %@", originalHTMLWithScriptsInjected]];
Run Code Online (Sandbox Code Playgroud)

脚本似乎是注入的,但没有运行.

我使用它的唯一方法是使用ASIHTTPRequest库来发出实际请求,但最后我遇到了登录表单的问题,除此之外,我必须在这种情况下每次请求两次.

我可能会做一些不可能的事情,或者我只是做错了.那么,如何在现有的UIWebView上调用带有从Web加载的内容的用户脚本?

编辑:

这里有一些代码,包括@rich提出的更改:

 //
 //  Run the remaining scripts
 //

NSMutableString *scriptTextToInject = [[NSMutableString alloc]init];

//
//  Add each script into the page
//

for (Userscript *script in scriptsToExecute) {

    //
    //  Read the userscript
    //

    NSString *scriptToLoad = [NSString stringWithContentsOfURL:[NSURL URLWithString:script.pathToScript] encoding:NSUTF8StringEncoding error:&error];

    NSLog(@"Script to load: %@", scriptToLoad);

    [scriptTextToInject appendFormat:@"%@\n\n",scriptToLoad];
}

NSString *documentHeadBefore = [self.browser stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('head')[0].innerHTML"];

//
//  Inject the scripts
//

NSString *scriptWrappedInATag = [NSString stringWithFormat:@"window.onload() = function(){var script = document.createElement('script');\n"
                                 "script.charset = 'UTF-8'"
                                 "script.setAttribute(\"type\",\"text/javascript\");\n"
                                 "text = \"function u(){\n"
                                 "%@"
                                 "}\";\n"
                                 "document.getElementsByTagName('head')[0].appendChild(script);}", scriptTextToInject];
NSLog(@"Scripts wrapped in a tag: %@", scriptWrappedInATag);

NSString *runResults = [self.browser stringByEvaluatingJavaScriptFromString:@"u();"];

NSString *documentHeadAfter = [self.browser stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('head')[0].innerHTML"];

NSLog(@"Before: %@ \n\n\n\n After: %@", documentHeadBefore, documentHeadAfter);
Run Code Online (Sandbox Code Playgroud)

ric*_*ich 5

下面是执行此操作的一个示例。我也遇到了同样的问题,直到我意识到需要将js注入到页面中。为了正确注入js,你需要将其写入dom的头部,如下所示。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
 [webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');"  
 "script.type = 'text/javascript';"  
 "script.text = \"function myFunction() { "  
 "window.scrollTo(100,100)"
 "}\";"  
 "document.getElementsByTagName('head')[0].appendChild(script);"];  

 [webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];
}    
Run Code Online (Sandbox Code Playgroud)