WKUserScript does not work

I want to add a script using the WKWebview API. For some reason, it does not work, and I cannot figure it out. I tried debugging in the Safari developer console and I can not find the JavaScript code there.

The implementation code is as follows:

 NSString *js = @"document.body.style.background = \"#FF0000\";"; NSString *myScriptSource = @"alert('Hello, World!')"; WKUserScript *s = [[WKUserScript alloc] initWithSource:myScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; WKUserContentController *c = [[WKUserContentController alloc] init]; [c addUserScript:s]; WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init]; conf.userContentController = c; WKWebView *webview = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:conf]; [self.view addSubview:webview]; webview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // Do any additional setup after loading the view, typically from a nib. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]]; [webview loadRequest:request]; }); 
+6
source share
2 answers

Please use this code and add a script message handler and set the navigation delegate

 NSString *js = @"document.body.style.background = \"#FF0000\";"; NSString *myScriptSource = @"alert('Hello, World!')"; WKUserScript *s = [[WKUserScript alloc] initWithSource:myScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; WKUserContentController *c = [[WKUserContentController alloc] init]; [c addUserScript:s]; // Add a script message handler for receiving "buttonClicked" event notifications posted from the JS document using window.webkit.messageHandlers.buttonClicked.postMessage script message [c addScriptMessageHandler:self name:@"buttonClicked"]; WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init]; conf.userContentController = c; WKWebView *webview = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:conf]; [self.view addSubview:webview]; webview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // Do any additional setup after loading the view, typically from a nib. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]]; [webview loadRequest:request]; }); 

implement the script message handler "WKScriptMessageHandler" with the method name

 #pragma mark -WKScriptMessageHandler - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name isEqualToString:@"buttonClicked"]) { self.buttonClicked ++; } // JS objects are automatically mapped to ObjC objects id messageBody = message.body; if ([messageBody isKindOfClass:[NSDictionary class]]) { NSString* idOfTappedButton = messageBody[@"ButtonId"]; [self updateColorOfButtonWithId:idOfTappedButton]; } 

}

and post js message form like this

 var button = document.getElementById("clickMeButton"); button.addEventListener("click", function() { var messgeToPost = {'ButtonId':'clickMeButton'}; window.webkit.messageHandlers.buttonClicked.postMessage(messgeToPost); },false); 

you will get a callback

+2
source

alert is not implemented by default in WKWebView , so even if your script user is running, he will not notice anything. You need to implement runJavaScriptAlertPanelWithMessage :

 func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (() -> Void)) { let alert = UIAlertController.create(title: frame.request.url?.host, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in completionHandler() })) present(alert, animated: true, completion: nil) } 

I don’t think that the entered JavaScript really appears in the DOM anywhere, this property is internal to WKWebView .

0
source

Source: https://habr.com/ru/post/976275/


All Articles