如何将JavaScript中的值传递到iOS UIWebView?
解决iOS UIWebView中JS带参数传递到Swift原生的问题
你的问题核心在于:当网页点击触发带参数的JS函数时,原生Swift代码无法直接获取到网页生成的参数——你之前尝试的webView.stringByEvaluatingJavaScript(from: "buttonClickPAss(a,b,c)")之所以失败,是因为Swift环境里并没有定义a、b、c这些变量,JS执行时会报错,自然没有返回值。
下面给你几种可行的解决方案,从适配UIWebView的传统方案到更推荐的现代方案都有:
方案1:自定义URL Scheme(和Android思路一致)
这是最接近你Android实现的方法,让JS通过自定义协议的URL把参数传递给原生,原生在shouldStartLoadWithRequest里解析URL参数。
修改JS代码
让buttonClickPAss函数打开一个自定义协议的URL,把参数编码后附在URL上:
function buttonClickPAss(a,b,c) { // 编码参数避免特殊字符问题 const encodedA = encodeURIComponent(a); const encodedB = encodeURIComponent(b); const encodedC = encodeURIComponent(c); // 自定义协议:myapp://buttonclick?参数 window.location.href = `myapp://buttonclick?a=${encodedA}&b=${encodedB}&c=${encodedC}`; }
对应的Swift代码
在UIWebViewDelegate的shouldStartLoadWithRequest方法里拦截自定义URL并解析参数:
func webView(_ webView: UIWebView, shouldStartLoadWithRequest request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool { guard let url = request.url, url.scheme == "myapp" else { return true // 正常加载其他HTTP/HTTPS请求 } if url.host == "buttonclick" { // 解析URL里的参数 let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let aValue = components?.queryItems?.first(where: { $0.name == "a" })?.value ?? "" let bValue = components?.queryItems?.first(where: { $0.name == "b" })?.value ?? "" let cValue = components?.queryItems?.first(where: { $0.name == "c" })?.value ?? "" print("从JS收到的参数:a=\(aValue), b=\(bValue), c=\(cValue)") } return false // 不要加载这个自定义URL,避免页面跳转 }
方案2:通过全局变量+JSON传递
如果不想用自定义URL,也可以让JS把参数存到全局变量,再通知原生去读取:
修改JS代码
// 定义全局变量存储参数 let lastClickedParams = null; function buttonClickPAss(a,b,c) { lastClickedParams = {a: a, b: b, c: c}; // 触发一个自定义URL通知原生可以读取参数了 window.location.href = "myapp://fetchParams"; }
对应的Swift代码
func webView(_ webView: UIWebView, shouldStartLoadWithRequest request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool { guard let url = request.url, url.scheme == "myapp" else { return true } if url.host == "fetchParams" { // 调用JS获取全局变量的JSON字符串 let jsonString = webView.stringByEvaluatingJavaScript(from: "JSON.stringify(lastClickedParams)") ?? "" if !jsonString.isEmpty { // 解析JSON为Swift字典 if let data = jsonString.data(using: .utf8), let params = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: String] { print("解析后的参数:\(params)") } } return false } return true }
方案3:迁移到WKWebView(推荐)
因为UIWebView已经被苹果废弃,更推荐使用WKWebView,它提供了更安全、高效的JS-原生通信方式——WKScriptMessageHandler:
Swift代码实现
import WebKit class YourViewController: UIViewController, WKScriptMessageHandler { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 配置WKWebView,添加消息处理器 let config = WKWebViewConfiguration() config.userContentController.add(self, name: "buttonClickHandler") // 创建并添加WebView到视图 webView = WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) // 加载你的HTML页面(这里直接用字符串示例,也可以加载本地/远程HTML) let htmlContent = """ <html> <head> <script type="text/javascript"> function buttonClickPAss(a,b,c) { // 通过WKWebView的消息机制传递参数 window.webkit.messageHandlers.buttonClickHandler.postMessage({a: a, b: b, c: c}); return false; // 阻止链接默认跳转 } </script> </head> <body> <b><a href='#' onclick="buttonClickPAss('valueA','valueB','valueC');">点击这里</a></b> </body> </html> """ webView.loadHTMLString(htmlContent, baseURL: nil) } // 接收JS发来的消息 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "buttonClickHandler" { // 解析消息体里的参数 if let params = message.body as? [String: String] { let a = params["a"] ?? "" let b = params["b"] ?? "" let c = params["c"] ?? "" print("收到JS参数:a=\(a), b=\(b), c=\(c)") } } } }
这种方法不需要依赖URL跳转,通信更直接,也更符合苹果的现代开发规范。
内容的提问来源于stack exchange,提问作者milsha
相关产品推荐
相关产品推荐

