Swift中如何在UIWebView/WKWebView捕获网页console.log日志?
当然有办法实现啦!在Swift里,不管是用苹果现在主推的WKWebView,还是已经被废弃的UIWebView,都能捕获网页中console.log输出的日志,下面分别给你讲具体的实现方案:
一、WKWebView 捕获 console.log(推荐方案)
WKWebView本身提供了和JS交互的完善机制,咱们可以通过注入自定义JS脚本,把网页里的console.log内容转发给原生Swift代码。
具体步骤:
- 首先创建一个
WKUserScript,重写网页的console.log方法,让它把日志内容通过window.webkit.messageHandlers发送给原生:
// 注入的JS脚本:重写console.log,将消息发送给名为"consoleLogHandler"的处理器 let consoleScript = WKUserScript(source: """ console.log = function(message) { window.webkit.messageHandlers.consoleLogHandler.postMessage(message); }; """, injectionTime: .atDocumentStart, forMainFrameOnly: true)
- 配置
WKWebViewConfiguration,把上面的脚本添加进去:
let userContentController = WKUserContentController() userContentController.addUserScript(consoleScript) // 注册消息处理器,指定接收消息的对象(这里假设当前ViewController实现了WKScriptMessageHandler协议) userContentController.add(self, name: "consoleLogHandler") let configuration = WKWebViewConfiguration() configuration.userContentController = userContentController
- 创建WKWebView并实现
WKScriptMessageHandler协议的方法,接收并打印日志:
class ViewController: UIViewController, WKScriptMessageHandler { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 上面的配置代码放在这里,然后初始化webView webView = WKWebView(frame: view.bounds, configuration: configuration) view.addSubview(webView) // 加载测试网页,比如本地HTML或者远程URL let testHTML = "<html><body><script>console.log('Hello from webpage!');</script></body></html>" webView.loadHTMLString(testHTML, baseURL: nil) } // 接收JS发来的日志消息 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "consoleLogHandler" { print("网页console.log输出:\(message.body)") } } // 注意:记得在销毁时移除处理器,避免循环引用 deinit { webView.configuration.userContentController.removeScriptMessageHandler(forName: "consoleLogHandler") } }
二、UIWebView 捕获 console.log(不推荐,已废弃)
UIWebView在iOS 12之后就被苹果标记为废弃了,性能和安全性都不如WKWebView,如果你因为历史原因必须用它,可以试试下面的方法:
核心思路是让网页的console.log调用一个自定义的URL Scheme(比如myapp://consoleLog),然后通过UIWebView的代理方法拦截这个请求,解析出日志内容。
具体步骤:
- 注入JS脚本,重写
console.log,让它通过跳转自定义URL的方式传递日志:
// 在加载网页前注入脚本 let consoleScript = """ console.log = function(message) { var encodedMessage = encodeURIComponent(message); window.location.href = 'myapp://consoleLog?message=' + encodedMessage; }; """ webView.stringByEvaluatingJavaScript(from: consoleScript)
- 实现UIWebView的代理方法
webView(_:shouldStartLoadWith:navigationType:),拦截自定义URL并解析日志:
class ViewController: UIViewController, UIWebViewDelegate { var webView: UIWebView! override func viewDidLoad() { super.viewDidLoad() webView = UIWebView(frame: view.bounds) webView.delegate = self view.addSubview(webView) // 加载测试网页 let testHTML = "<html><body><script>console.log('Hello from UIWebView!');</script></body></html>" webView.loadHTMLString(testHTML, baseURL: nil) // 注入脚本 webView.stringByEvaluatingJavaScript(from: consoleScript) } func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool { guard let url = request.url, url.scheme == "myapp" else { return true // 不是自定义URL,正常加载 } if url.host == "consoleLog", let message = url.queryParameters?["message"], let decodedMessage = message.removingPercentEncoding { print("网页console.log输出:\(decodedMessage)") } return false // 拦截这个自定义请求,不实际跳转 } } // 给URL扩展一个解析query参数的方法 extension URL { var queryParameters: [String: String]? { guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), let queryItems = components.queryItems else { return nil } return queryItems.reduce(into: [String: String]()) { result, item in result[item.name] = item.value } } }
额外注意点:
- 优先使用WKWebView,苹果已经不再维护UIWebView,后续系统版本可能会彻底移除它;
- WKWebView的消息处理器要记得在
deinit中移除,防止循环引用导致内存泄漏; - 如果需要捕获
console.error、console.warn等其他日志类型,只需要在注入的JS脚本里重写对应的方法即可,逻辑和console.log一致。
内容的提问来源于stack exchange,提问作者tugceaktepe
相关产品推荐
相关产品推荐

