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

Swift WKWebView中window.close()触发后webViewDidClose未调用问题排查

问题原因

webViewDidClose(_:) 仅在由createWebViewWith代理方法创建的子窗口WKWebView调用window.close()时才会触发,你当前调用window.close()的是主WKWebView实例,主窗口的window.close()默认不会触发该代理方法,也不会有任何默认行为。

解决方法

方法一:注入JS拦截window.close(),通过消息通知原生关闭

通过WKUserScript拦截网页的window.close()调用,转而向原生发送消息,直接触发关闭逻辑:

  1. 配置WKWebView时注册消息处理器:
// 初始化用户内容控制器
let userContentController = WKUserContentController()
// 注册名为"closeWebView"的消息处理器
userContentController.add(self, name: "closeWebView")

// 配置WKWebViewConfiguration
let config = WKWebViewConfiguration()
config.userContentController = userContentController
config.uiDelegate = self

// 创建WKWebView
let webView = WKWebView(frame: view.bounds, configuration: config)
  1. 实现WKScriptMessageHandler代理接收消息:
extension YourViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard message.name == "closeWebView" else { return }
        dismiss(animated: true, completion: nil)
    }
}
  1. 注入拦截window.close()的脚本:
// 编写拦截脚本,替换原生window.close逻辑
let closeInterceptorScript = """
window.close = function() {
    if(confirm("confirm?")) {
        // 向原生发送关闭消息
        window.webkit.messageHandlers.closeWebView.postMessage(null);
    }
};
"""
// 创建用户脚本,在文档加载前注入主框架
let userScript = WKUserScript(source: closeInterceptorScript, 
                              injectionTime: .atDocumentStart, 
                              forMainFrameOnly: true)
userContentController.addUserScript(userScript)

方法二:修改网页JS逻辑(若有权限)

如果可以修改网页代码,直接让Common.Close方法调用原生消息通知,跳过window.close():

var Common = {
    Close : function (){
        if(confirm("confirm?")) {
            window.webkit.messageHandlers.closeWebView.postMessage(null);
        }
    }
}

之后按方法一的步骤注册消息处理器即可。

方法三:在确认回调中主动关闭(无需修改网页)

在你已实现的runJavaScriptConfirmPanelWithMessage方法中,判断确认消息内容,用户点击确认后直接关闭控制器:

func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    let alert = UIAlertController(title: message, message: nil, preferredStyle: .alert)
    
    alert.addAction(UIAlertAction(title: "cancel", style: .cancel) { _ in
        completionHandler(false)
    })
    alert.addAction(UIAlertAction(title: "ok", style: .default) { [weak self] _ in
        completionHandler(true)
        // 匹配关闭弹窗的消息,主动关闭控制器
        if message == "confirm?" {
            self?.dismiss(animated: true, completion: nil)
        }
    })
    
    DispatchQueue.main.async {
        self.present(alert, animated: true)
    }
}

注意:如果网页中有其他相同内容的确认弹窗,可能会误触发,建议和网页端约定唯一的确认文本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:05:44