Как я могу внедрить пользовательский скрипт на iOS? - PullRequest
13 голосов
/ 06 августа 2011

Я работаю над Fahrii , который по сути является мобильным браузером с поддержкой usercript. В данный момент у меня возникают проблемы с вызовом сценариев на веб-странице, загруженной в UIWebView. Я хотел бы сохранить эти открытые API, если это возможно. Если нет, то, по крайней мере, было бы неплохо проверить концепцию, поэтому я могу лучше понять, как это работает. Я пытаюсь сделать это методом webViewDidFinishLoad:.

Я попытался сделать инъекцию, прочитав содержимое webView (используя JavaScript), а затем загрузив его обратно с loadHTML:baseURL:, но это вызывает бесконечную рекурсию. (Завершенная загрузка вызывает внедрение скрипта, что, в свою очередь, вызывает завершенную «загрузку».)

Далее я попробовал что-то вроде этого:

    [self.browser stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.innerHTML = %@", originalHTMLWithScriptsInjected]];

Сценарий, похоже, внедрен, но не запущен.

Единственный способ заставить это работать - использовать библиотеку ASIHTTPRequest для выполнения реальных запросов, но затем у меня возникли проблемы с формами входа, кроме того, в этом случае мне приходилось делать каждый запрос дважды.

Возможно, я делаю что-то, что либо невозможно, либо я делаю это неправильно. Итак, как я могу вызвать пользовательский скрипт в существующем UIWebView с контентом, загруженным из Интернета?

Редактировать:

Вот еще немного кода, включая изменения, предложенные @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);

Ответы [ 2 ]

4 голосов
/ 08 августа 2011

Пример того, как это сделать, ниже.У меня была та же самая проблема, пока я не понял, что 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();"];
}    
1 голос
/ 30 декабря 2011

Вы должны напрямую передать строку в stringByEvaluatingJavaScriptFromString: метод, например:

NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"Script To Be Run"];
...