如何在Swift代码中调用WebView内的JavaScript函数并传参?
如何在Swift中实现WebView与JavaScript的带参数fullCode交互
我来帮你搞定这个问题!你当前的Swift代码存在方法签名不匹配、未正确配置WebView交互桥接的问题,下面分两种常用的WebView场景给出完整的正确实现:
场景1:使用WKWebView(苹果推荐,iOS 8+)
WKWebView是现在苹果主推的WebView组件,用WKScriptMessageHandler来处理JS和原生的交互,步骤如下:
1. 配置WKWebView并添加消息监听
让你的ViewController遵循WKScriptMessageHandler协议,初始化WebView时配置好交互逻辑:
import UIKit import WebKit class ViewController: UIViewController, WKScriptMessageHandler { var webView: WKWebView! var receivedHtmlCode: String? // 存储JS传递的HTML代码 override func viewDidLoad() { super.viewDidLoad() // 配置WebView参数 let webConfig = WKWebViewConfiguration() let userContentController = WKUserContentController() // 添加消息监听,"fullCode"是JS调用时的标识,要和JS端对应 userContentController.add(self, name: "fullCode") webConfig.userContentController = userContentController webView = WKWebView(frame: view.bounds, configuration: webConfig) view.addSubview(webView) // 加载你的网页(替换成你的实际URL或本地HTML路径) if let localHtmlPath = Bundle.main.path(forResource: "yourPage", ofType: "html") { let htmlUrl = URL(fileURLWithPath: localHtmlPath) webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl.deletingLastPathComponent()) } } // 接收JS消息的核心方法 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard message.name == "fullCode" else { return } // 解析JS传递的字符串参数 if let htmlCode = message.body as? String { receivedHtmlCode = htmlCode print("收到JS传来的HTML代码:\(htmlCode)") // 这里可以添加你后续的业务逻辑 } } // 记得移除监听,避免内存泄漏 deinit { webView.configuration.userContentController.removeScriptMessageHandler(forName: "fullCode") } }
2. 修改JavaScript代码适配WKWebView
原来的JS调用Android.fullCode需要改成WKWebView的标准调用方式:
function draft(){ var getAllHtmlCode = getHtml(); window.webkit.messageHandlers.fullCode.postMessage(getAllHtmlCode); }
场景2:使用UIWebView(不推荐,iOS 12+已废弃)
如果你的项目还在使用旧的UIWebView,可以用JavaScriptCore框架实现:
1. 配置UIWebView并注入JS桥接对象
import UIKit import JavaScriptCore class ViewController: UIViewController, UIWebViewDelegate { var webView: UIWebView! var receivedHtmlCode: String? // 定义JS导出协议,必须继承JSExport @objc protocol WebViewJSBridge: JSExport { // 方法名要和JS里的`fullCode`完全一致(注意大小写!) func fullCode(_ htmlCode: String) } // 实现桥接逻辑的类 @objc class JSBridgeHandler: NSObject, WebViewJSBridge { weak var parentVC: ViewController? init(vc: ViewController) { parentVC = vc } func fullCode(_ htmlCode: String) { parentVC?.receivedHtmlCode = htmlCode print("收到JS传来的HTML代码:\(htmlCode)") } } override func viewDidLoad() { super.viewDidLoad() webView = UIWebView(frame: view.bounds) webView.delegate = self view.addSubview(webView) // 加载你的网页 if let localHtmlPath = Bundle.main.path(forResource: "yourPage", ofType: "html") { let htmlUrl = URL(fileURLWithPath: localHtmlPath) webView.loadRequest(URLRequest(url: htmlUrl)) } } // 网页加载完成后注入桥接对象 func webViewDidFinishLoad(_ webView: UIWebView) { guard let jsContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext else { return } // 注入名为"Android"的桥接对象,和你原JS代码的调用保持一致 let bridge = JSBridgeHandler(vc: self) jsContext.setObject(bridge, forKeyedSubscript: "Android" as (NSCopying & NSObjectProtocol)) } }
2. 保持原JavaScript代码不变
这种情况下,你原来的JS代码Android.fullCode(getAllHtmlCode)可以直接使用,不需要修改。
几个关键注意点
- 方法名大小写必须一致:你原来的Swift代码写的是
fullcode(小写c),但JS里调用的是fullCode(大写C),这会导致无法匹配,一定要统一! - 参数类型要匹配:确保JS传递的参数类型和Swift接收的类型一致,这里是字符串,所以转成
String即可。 - 优先使用WKWebView:UIWebView已经被苹果废弃,不再提供更新和维护,建议新项目或迭代时切换到WKWebView。
内容的提问来源于stack exchange,提问作者Faizul Karim




