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

SwiftUI中WKWebView调用evaluateJavaScript返回nil的原因排查

解决WebView调用evaluateJavaScript返回nil的问题

我看了你的代码,问题大概率出在网页还没加载完成就执行了JavaScript代码上,这是使用WKWebView时很容易踩的坑!

核心问题分析

webView.load(request)是异步操作,调用后并不会立刻完成网页加载和DOM渲染。你紧接着就调用evaluateJavaScript,这时候网页可能还在加载中,document.getElementById('ses')根本找不到对应的元素,自然返回nil。

解决方法:监听网页加载完成事件

我们可以通过实现WKNavigationDelegate,在网页完全加载完成后再执行JS代码。具体步骤如下:

  1. 给WebView结构体添加一个Coordinator类,用来充当WKNavigationDelegate的代理
  2. 在makeUIView方法中给webView设置navigationDelegate
  3. 在代理方法webView(_:didFinish:)里执行获取输入框值的JS代码

修改后的完整代码如下:

import SwiftUI
import WebKit

struct ContentView: View {
    var body: some View {
        WebView().edgesIgnoringSafeArea(.all)
    }
}

struct WebView: UIViewRepresentable {
    // 创建Coordinator作为代理
    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebView
        
        init(_ parent: WebView) {
            self.parent = parent
        }
        
        // 网页加载完成时触发
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.getElementById('ses').value") { (result, error) in
                if let error = error {
                    print("执行JS出错:\(error.localizedDescription)")
                    return
                }
                print("输入框的值:\(result ?? "未找到元素")")
            }
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.scrollView.isScrollEnabled = false
        // 设置代理
        webView.navigationDelegate = context.coordinator
        return webView
    }
    
    func updateUIView(_ webView: WKWebView, context: Context) {
        let liveView = "https://**/"
        if let url = URL(string: liveView) {
            let request = URLRequest(url: url)
            webView.load(request)
            // 这里不再直接执行JS,交给代理方法处理
        }
    }
}

其他可能的排查方向

如果按照上面的方法还是返回nil,可以检查以下几点:

  • 元素ID是否正确:确认网页中输入框的ID确实是ses,注意大小写和拼写错误
  • 元素是否在iframe内:如果输入框嵌套在<iframe>里,需要先获取iframe的contentDocument再查找元素,比如:
    document.getElementById('iframeId').contentDocument.getElementById('ses').value
    
  • 元素是否是动态生成的:如果输入框是通过Vue、React等框架动态渲染的,即使页面加载完成,元素可能还没生成。这种情况可以考虑延迟执行JS,或者监听DOM变化事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:11:38