You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 09:15:02