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

特定网页在WKWebView仅显示白屏的问题排查咨询

针对WKWebView加载特定网页白屏的排查方案

以下是针对你遇到的「特定网页在Safari/SFSafariViewController正常加载,但WKWebView白屏且无报错」问题的具体排查步骤和解决方案:

1. 验证User-Agent差异导致的内容适配问题

WKWebView的默认User-Agent与Safari存在差异,部分网站会根据UA返回不同的页面内容,甚至拒绝为非Safari UA提供完整页面。

排查操作:
在makeUIView方法中打印当前WKWebView的UA,并与Safari的UA对比(Safari中访问about:version可查看):

func makeUIView(context: Context) -> WKWebView  {
    let wkwebView = WKWebView()
    print("WKWebView UA: \(wkwebView.customUserAgent ?? wkwebView.configuration.defaultWebpagePreferences.userAgent ?? "")")
    wkwebView.navigationDelegate = context.coordinator
    wkwebView.load(URLRequest(url: url))
    return wkwebView
}

修复方案:
手动将WKWebView的UA设置为Safari的UA:

func makeUIView(context: Context) -> WKWebView  {
    let config = WKWebViewConfiguration()
    // 替换为你从Safari获取的实际UA
    config.defaultWebpagePreferences.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1"
    let wkwebView = WKWebView(frame: .zero, configuration: config)
    wkwebView.navigationDelegate = context.coordinator
    wkwebView.load(URLRequest(url: url))
    return wkwebView
}

2. 排查Content Security Policy (CSP) 限制

部分网站的CSP规则可能严格限制WKWebView加载资源(比如内联JS、外部脚本),而Safari对CSP的执行宽松度更高,导致页面白屏但无报错。

排查操作:
扩展Coordinator的功能,监听网页控制台日志,捕获CSP相关错误:

  1. 让Coordinator实现WKScriptMessageHandler协议,并添加日志监听:
class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
    var parent: WebView
    init(_ parent: WebView) {
        self.parent = parent
    }
    
    // 原有导航代理方法...
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("loading didFinish")
        parent.isLoading = false
        // 注入JS转发控制台日志
        webView.evaluateJavaScript("""
            console.log = function(message) {
                window.webkit.messageHandlers.logHandler.postMessage(message);
            };
            console.error = function(message) {
                window.webkit.messageHandlers.logHandler.postMessage('ERROR: ' + message);
            };
            """) { _, error in
            if let error = error {
                print("JS注入失败: \(error)")
            }
        }
    }
    
    // 接收网页控制台日志
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "logHandler" {
            print("网页控制台: \(message.body)")
        }
    }
}
  1. 在WKWebView配置中添加消息处理器:
func makeUIView(context: Context) -> WKWebView  {
    let config = WKWebViewConfiguration()
    let userContentController = WKUserContentController()
    userContentController.add(context.coordinator, name: "logHandler")
    config.userContentController = userContentController
    let wkwebView = WKWebView(frame: .zero, configuration: config)
    wkwebView.navigationDelegate = context.coordinator
    wkwebView.load(URLRequest(url: url))
    return wkwebView
}

通过Xcode控制台输出,查看是否有CSP相关的错误提示。

修复方案:
如果确认是CSP问题,可尝试联系网站管理员调整CSP规则;若网站允许,也可在请求中添加自定义Header(需验证网站是否支持)。

3. 检查ATS(App Transport Security)配置

如果目标网页是HTTP协议,或HTTPS证书存在问题,WKWebView会默认阻止加载,而Safari允许加载这类页面。

排查操作:
完善错误捕获逻辑,打印详细错误信息:

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    print("加载失败: \(error)")
    if let nsError = error as NSError? {
        print("错误码: \(nsError.code), 域名: \(nsError.domain)")
        print("错误详情: \(nsError.userInfo)")
    }
    parent.isLoading = false
    parent.error = error
}

// 补充捕获导航过程中的错误
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    print("导航失败: \(error)")
    parent.isLoading = false
    parent.error = error
}

若错误码为-1022(ATS阻止HTTP)或-1202(证书不被信任),则对应ATS配置问题。

修复方案:

  • 针对HTTP页面:在Info.plist中添加ATS例外(仅针对目标域名,避免全局关闭ATS):
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>你的目标域名.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>
    </dict>
</dict>
  • 针对自签名证书(仅测试环境使用,生产环境不建议):在导航代理中信任证书:
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard let serverTrust = challenge.protectionSpace.serverTrust else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    let credential = URLCredential(trust: serverTrust)
    completionHandler(.useCredential, credential)
}

4. 确保JavaScript和存储权限开启

部分网页依赖JavaScript或本地存储(localStorage/sessionStorage),WKWebView默认启用JavaScript,但需确认配置未被修改。

修复方案:
在WKWebView配置中明确开启相关权限:

func makeUIView(context: Context) -> WKWebView  {
    let config = WKWebViewConfiguration()
    // 开启JavaScript
    config.defaultWebpagePreferences.allowsContentJavaScript = true
    // 启用本地存储
    config.websiteDataStore = WKWebsiteDataStore.default()
    let wkwebView = WKWebView(frame: .zero, configuration: config)
    wkwebView.navigationDelegate = context.coordinator
    wkwebView.load(URLRequest(url: url))
    return wkwebView
}

5. 修复网页视口适配问题

部分网页对WKWebView的视口适配处理不佳,导致内容被隐藏或缩放异常,看起来是白屏。

修复方案:
注入视口适配的JS代码,强制网页适配设备宽度:

func makeUIView(context: Context) -> WKWebView  {
    let config = WKWebViewConfiguration()
    let userContentController = WKUserContentController()
    // 注入视口适配脚本
    let viewportScript = WKUserScript(
        source: """
        var meta = document.createElement('meta');
        meta.setAttribute('name', 'viewport');
        meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
        document.head.appendChild(meta);
        """,
        injectionTime: .atDocumentStart,
        forMainFrameOnly: true
    )
    userContentController.addUserScript(viewportScript)
    config.userContentController = userContentController
    let wkwebView = WKWebView(frame: .zero, configuration: config)
    wkwebView.navigationDelegate = context.coordinator
    wkwebView.load(URLRequest(url: url))
    return wkwebView
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:09:58