I am trying to read the console logs of webapp that is loaded in my WkWebview programmatically.
so far in my research it's not possible.
How can I achieve this?
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
}
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)
}
}
}
来源:https://stackoverflow.com/questions/37159648/how-to-read-console-logs-of-wkwebview-programmatically
