WKWebView将web中的`console.log`输出到控制台、传值

1,205 阅读1分钟

前提:一般情况下,对于网页中javascript中输出的log,是不会在XCode的控制台输出的,为了调试方便,更加清楚的获取到javascript中的log,需要让js中的log也显示在XCode的控制台中。

这里有一个非常实用的好处:前端可以通过简单的调用 console.log("hello world") 便可以将数据("hello world")传递到移动端

Android:
实现webview的setWebChromeClient系统自带方法onConsoleMessage,即可获取web端console.log内容。

mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
                ParachuteLog.d(TAG, "onConsoleMessage: " + consoleMessage.messageLevel() + " " + consoleMessage.message());
                // TODO: convert consoleMessage.messageLevel() to int corresponding to native value
                return true;
            }
}

iOS:
具体解决方案:重写js中的console.log方法,在重写的方法中触发调用原生方法,将log的输出内容传递出去。

1、这个类主要用来做native与JavaScript的交互管理

    WKUserContentController * wkUserContent= [[WKUserContentController alloc] init];

    self.scriptMessage = [[BMScriptMessageHandler alloc]init];

    [wkUserContent addScriptMessageHandler:self.scriptMessage name:@"log"];

2、重写前端console.log,注入JS事件

    NSString * consoleLog = @"console.log = (function(oriLogFunc){return function(str){oriLogFunc.call(console,str);window.webkit.messageHandlers.log.postMessage(str);}})(console.log);";

    WKUserScript *userScriptLog = [[WKUserScript alloc] initWithSource:consoleLog injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];// forMainFrameOnly:NO(全局窗口),yes(只限主窗口)

    [wkUserContent addUserScript:userScriptLog];

3、实现WKScriptMessageHandler代理方法,在代理方法中根据name执行输出。

@implementation BMScriptMessageHandler

/*
 @abstract Invoked when a script message is received from a webpage.
 @param userContentController The user content controller invoking the
 delegate method.
 @param message The script message received.
 */

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;{

    NSString * msgName = message.name;

    NSString * body = [NSString stringWithFormat:@"%@",message.body];
    
    if ([msgName isEqualToString:@"log"]) {

        NSLog(@"%@",body);
    }
}

@end

4、记得移除

- (void)dealloc{

    NSLog(@"%s", __func__ );

    [self.mWebView.configuration.userContentController removeScriptMessageHandlerForName:@"log"];

    self.scriptMessage = nil;

}

5、测试代码,编写一段js代码,放入一个html文件中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type="text/css">
        .console{
            width: 100;
            height: 100;
            background-color: red;
            display: flex;
        }
    </style>
    <script type="text/javascript">
        function consoleSendToNative() {
            console.log('hello world');
        }
    </script>
</head>
<body>
    <div class="console" onclick="consoleSendToNative()">Jan</div>
</body>
</html>

6、测试结果

XXXXXXXXXXXXXXXXXXXX[39034:7578056] hello world