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

Swift中setURLSchemeHandler导致WKWebView内存泄漏:如何在销毁视图控制器前移除Scheme Handler?

解决WKURLSchemeHandler导致的循环引用问题

这确实是使用WKWebView自定义Scheme Handler时非常容易踩的坑!你遇到的deinit不触发的问题,本质是WKWebViewConfiguration通过setURLSchemeHandler(_:forURLScheme:)持有了self的强引用,而你的视图控制器又持有WKWebView,形成了循环引用链:ViewController → WKWebView → WKWebViewConfiguration → WKURLSchemeHandler(self) → ViewController,导致内存无法正常释放。

解决方案:主动移除Scheme Handler并清理WebView

要打破这个循环,你需要在视图控制器被销毁前(注意不能等到deinit,因为循环引用下它根本不会执行),主动调用WKWebViewConfiguration的移除方法,同时清理WKWebView的引用。

具体实现步骤:

  1. 在合适的生命周期方法中(比如viewWillDisappear),先移除对应的Scheme Handler
  2. 将WKWebView从父视图移除并置为nil,彻底打破引用链

下面是完整的代码示例:

class YourViewController: UIViewController, WKURLSchemeHandler {
    // 用可选类型持有WKWebView,方便后续置空
    var webView: WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let config = WKWebViewConfiguration()
        config.setURLSchemeHandler(self, forURLScheme: "local")
        
        webView = WKWebView(frame: view.bounds, configuration: config)
        view.addSubview(webView!)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // 仅当控制器被从父容器移除时(比如返回上一页)才执行清理
        if isMovingFromParent {
            // 第一步:移除Scheme Handler,让Configuration释放对self的强引用
            webView?.configuration.removeURLSchemeHandler(forURLScheme: "local")
            
            // 第二步:清理WebView的引用
            webView?.removeFromSuperview()
            webView = nil
        }
    }

    // MARK: - WKURLSchemeHandler 协议实现
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        // 处理你的"local" scheme请求逻辑
    }

    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
        // 停止请求的处理逻辑(比如取消网络请求、释放资源)
    }

    deinit {
        print("✅ ViewController 成功销毁!")
    }
}

关键说明:

  • removeURLSchemeHandler(forURLScheme:)是WKWebViewConfiguration专门提供的移除方法,调用后会释放对之前设置的handler的强引用
  • 用isMovingFromParent判断可以确保只在控制器被销毁的场景执行清理,避免push其他控制器时误操作
  • 将webView置为nil是最后一步,确保视图控制器不再持有webView的强引用,彻底打破循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:12:40