How to read console logs of wkwebview programmatically

a 夏天 提交于 2019-12-05 01:03:45

Please use this beautiful in-app "Bridge"

Edit:

self.webView = [[WBWKWebView alloc] initWithFrame:self.view.bounds];
self.webView.JSBridge.interfaceName = @"WKWebViewBridge";
WBWebDebugConsoleViewController * controller = [[WBWebDebugConsoleViewController alloc] initWithConsole:_webView.console];

Then , you can use the delegate method:

- (void)webDebugInspectCurrentSelectedElement:(id)sender
{
// To use the referenced log values
}

It's possible to connect Safari browser on you Mac to the WKWebView and get access to the console.

From Safari, open "Develop" tab and while the iOS Simulator is running with the WKWebView open - just click it to open the console. See:

noxo

You can re-evaluate (override) Javascript console.log() default implementation to use window.webkit.messageHandlers.postMessage(msg) to pass message forwards instead. And then intercept the javascript postMessage(msg) call at native code using WKScriptMessageHandler ::didReceiveScriptMessage to get the logged message.

Step 1) Re-evaluate console.log default implementation to use postMessage()

// javascript to override console.log to use messageHandlers.postmessage
NSString * js = @"var console = { log: function(msg){window.webkit.messageHandlers.logging.postMessage(msg) } };";
// evaluate js to wkwebview
[self.webView evaluateJavaScript:js completionHandler:^(id _Nullable ignored, NSError * _Nullable error) {
    if (error != nil)
        NSLog(@"installation of console.log() failed: %@", error);
}];

Step 2) Intercept javascript postMessage in native code at WKScriptMessageHandler::didReceiveScriptMessage

- (void)viewDidLoad
{
    // create message handler named "logging"
    WKUserContentController *ucc = [[WKUserContentController alloc] init];
    [ucc addScriptMessageHandler:self name:@"logging"];
    // assign usercontentcontroller to configuration    
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    [configuration setUserContentController:ucc];
    // assign configuration to wkwebview    
    self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) configuration:configuration];
}


- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    // what ever were logged with console.log() in wkwebview arrives here in message.body property
    NSLog(@"log: %@", message.body);
}

Normally the console logging is defined in js as

    "window.addEventListener("message",function(e){console.log(e.data)});"

My answer was adapted from handling-javascript-events-in-wkwebview!

Initialize WKWebView with configuration

    let config = WKWebViewConfiguration()
    let source = "document.addEventListener('message', function(e){
     window.webkit.messageHandlers.iosListener.postMessage(e.data); })"
    let script = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
    config.userContentController.addUserScript(script)
    config.userContentController.add(self, name: "iosListener")
    webView = WKWebView(frame: UIScreen.main.bounds, configuration: config)

Or use KVO observe property "estimatedProgress" and inject js by evalueate JavaScript

    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
    {
        if ([keyPath isEqualToString:@"estimatedProgress"])
        {
            CGFloat progress = [change[NSKeyValueChangeNewKey] floatValue];
            if (progress>= 0.9)
            {
                NSString *jsCmd = @"window.addEventListener(\"message\",function(e){window.webkit.messageHandlers.iosListener.postMessage(e.data)});";
        //@"document.addEventListener('click', function(e){ window.webkit.messageHandlers.iosListener.postMessage('Customize click'); })";

                [_webView evaluateJavaScript:jsCmd completionHandler:^(id _Nullable obj, NSError * _Nullable error) {
                    NSLog(@"error:%@",error);
                }];
            }
        }
    }

implement the WKScriptMessageHandler protocol to receive the message:

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) 
    {
            print("message: \(message.body)")
            // and whatever other actions you want to take
    }

Swift 4.2 & 5

 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
      webView.evaluateJavaScript("your javascript string") { (value, error) in
          if let errorMessage = (error! as NSError).userInfo["WKJavaScriptExceptionMessage"] as? String {
                print(errorMessage)
          }
      }
 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!