SwiftUI下UIWebView升级为WKWebView的Javascript交互实现咨询
WKWebView(SwiftUI)功能实现方案
前置准备
- 已完成Firebase Messaging集成,可正常获取FCM Token
- 已获取到设备UDID(原有逻辑中需要传入JS函数的参数)
代码改造(仅需修改Home.swift)
改造后的完整代码如下:
import SwiftUI import WebKit import FirebaseMessaging // 已集成Firebase可直接导入使用 struct Home: UIViewRepresentable{ let url: URL? // 存储FCM Token,可替换为你全局获取Token的逻辑 private var fcmToken: String? { // 生产环境建议使用异步回调方法获取,避免阻塞主线程 try? Messaging.messaging().token() } // 存储设备UDID,替换为你自己的UDID获取逻辑 private let udid = UIDevice.current.identifierForVendor?.uuidString ?? "" func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let prefs = WKWebpagePreferences() prefs.allowsContentJavaScript = true let config = WKWebViewConfiguration() config.defaultWebpagePreferences = prefs let webView = WKWebView ( frame: .zero, configuration: config) // 绑定代理 webView.navigationDelegate = context.coordinator webView.uiDelegate = context.coordinator webView.isUserInteractionEnabled = true return webView } func updateUIView(_ uiView: WKWebView, context: Context) { guard let homeURL = url else { return } let request = URLRequest(url: homeURL) uiView.load(request) } // 代理协调器 class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate { var parent: Home init(_ parent: Home) { self.parent = parent } // 页面加载完成回调,对应原UIWebView的webViewDidFinishLoad func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { // 1. 注入自定义JS函数 let injectJS = "var BYB_GetFcmTokens = function(udid,token){ alert(udid);alert(token); /* 此处可添加向后端发请求存MySQL的JS代码 */ };" webView.evaluateJavaScript(injectJS) { _, error in if let error = error { print("JS注入失败: \(error.localizedDescription)") return } // 2. 注入成功后调用JS函数传入参数 guard let token = self.parent.fcmToken, !self.parent.udid.isEmpty else { return } let callJS = "BYB_GetFcmTokens('\(self.parent.udid)', '\(token)');" webView.evaluateJavaScript(callJS) { _, error in if let error = error { print("调用JS函数失败: \(error.localizedDescription)") } } } } // 实现WKUIDelegate处理JS的alert弹窗,否则alert默认不会弹出 func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { _ in completionHandler() })) // 获取当前顶层控制器弹出alert if let topVC = UIApplication.shared.windows.first?.rootViewController?.topMostViewController() { topVC.present(alert, animated: true) } else { completionHandler() } } } } // 扩展获取当前顶层控制器,用于弹出alert extension UIViewController { func topMostViewController() -> UIViewController { if let presented = self.presentedViewController { return presented.topMostViewController() } if let nav = self as? UINavigationController { return nav.topViewController?.topMostViewController() ?? nav } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMostViewController() ?? tab } return self } }
功能说明
- 页面加载完成后会自动注入自定义的
BYB_GetFcmTokensJS函数 - 注入成功后自动传入设备UDID和FCM Token调用该函数,触发alert弹窗
- 可直接在注入的JS函数内添加向后端发送请求的代码,将Token存入MySQL后即可实现后续定向推送功能
注意事项
- 若FCM Token是异步获取,建议在Token回调返回后再触发JS调用,避免参数为空
- 若不需要原生处理alert弹窗,也可直接在JS函数内完成Token上传逻辑,无需实现
WKUIDelegate相关代码
内容的提问来源于stack exchange,提问作者MatteoS.
相关产品推荐
相关产品推荐

