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

Swift中如何实现WKWebView的JavaScript定时注入与通信?

WKWebView定时执行JS/传参通信解决方案

首先明确:完全可以实现你要的需求,不需要局限在加载首尾注入JS,以下是3种可落地的方案,优先推荐第一种:

方案1:原生侧定时调用已注入的JS方法(最优适配你的业务)

WKWebView自带evaluateJavaScript(_:completionHandler:)API,支持在WebView存活的任意阶段执行JS代码,不需要重复注入脚本,只需要你在页面加载阶段提前把发送POST请求的JS逻辑注入成全局方法,后续原生侧定时调用传参即可。

实现代码示例:

import WebKit

class YourWebViewController: UIViewController, WKNavigationDelegate {
    var webView: WKWebView!
    // 用weak修饰Timer避免循环引用
    weak var gpsUploadTimer: Timer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始化WebView配置,提前注入你的基础JS逻辑(包含发送POST的方法postGPSSpeed)
        let config = WKWebViewConfiguration()
        let jsCode = "function postGPSSpeed(speed) { \
            fetch('你的上传接口地址', { \
                method: 'POST', \
                headers: { '你的共用请求头key': '共用请求头value' }, \
                body: JSON.stringify({speed: speed}) \
            }) \
        }"
        let userScript = WKUserScript(source: jsCode, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
        config.userContentController.addUserScript(userScript)
        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        view.addSubview(webView)
        // 加载你的目标页面
        webView.load(URLRequest(url: URL(string: "你的页面地址")!))
    }
    
    // 页面加载完成后启动10秒定时任务
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        gpsUploadTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { [weak self] _ in
            guard let self = self else { return }
            // 调用你自己的方法获取当前最新的GPS速度值
            let currentSpeed = self.getCurrentGPSSpeed()
            // 构造执行JS的代码,传入速度参数
            let execJS = "postGPSSpeed(\(currentSpeed));"
            self.webView.evaluateJavaScript(execJS) { _, error in
                if let err = error {
                    print("执行JS失败:\(err.localizedDescription)")
                }
            }
        }
    }
    
    // 你的获取GPS速度的自有方法,这里仅做示例
    func getCurrentGPSSpeed() -> Double {
        // 替换为你实际的GPS取值逻辑
        return 30.5
    }
    
    // 页面销毁时停止定时器,避免内存泄漏
    deinit {
        gpsUploadTimer?.invalidate()
    }
}

方案2:注入JS侧自行实现定时逻辑

如果不需要原生侧控制定时启停,你可以直接在初始注入的JS代码里加入setInterval定时逻辑,完全不需要原生侧后续操作:
你可以在初始注入的JS代码中加入以下逻辑:

setInterval(() => {
    // 如果你需要获取原生侧最新的GPS数据,可以通过WKScriptMessageHandler主动向原生发消息获取
    // 这里写你的POST请求发送逻辑
}, 10000)

方案3:DOM自定义事件通信

你也可以通过监听自定义DOM事件的方式实现通信,不需要提前约定全局JS方法:

  1. 初始注入的JS里添加事件监听:
document.addEventListener('uploadSpeedEvent', (event) => {
    const speed = event.detail.speed
    // 执行POST发送逻辑
})
  1. 原生侧需要触发时执行以下代码即可:
let triggerJS = "document.dispatchEvent(new CustomEvent('uploadSpeedEvent', {detail: {speed: \(currentSpeed)}}));"
webView.evaluateJavaScript(triggerJS)

方案选择建议

优先选方案1,逻辑最清晰,原生侧可以完全控制定时的启停、参数传递,不需要重复注入JS,性能最优,完全适配你上传GPS速度的业务需求。

内容的提问来源于stack exchange,提问作者Tatsurou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:18:01