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

自定义类中UIWebView代理方法无法触发的问题排查

问题分析与解决方案

嘿,折腾5小时确实够闹心的,我一眼就瞅出问题出在哪了!

核心问题:对象被提前回收(ARC自动引用计数搞的鬼)

你在showPopupTapped方法里创建的WebViewAsPopup是个局部变量,当这个方法执行完毕后,ARC会立刻把这个实例回收掉。而你把它设为UIWebView的代理(代理默认是弱引用),这直接导致两个问题:

  • 当webview尝试调用代理方法时,代理对象已经不存在了,自然就崩溃了
  • 你的webViewDidStartLoad和webViewDidFinishLoad回调也根本没机会触发

修复步骤&修改后的代码

第一步:修改WebViewAsPopup.swift,把弹窗控件改成实例属性

让控件和WebViewAsPopup实例绑定,避免被提前释放:

// WebViewAsPopup.swift
import UIKit

class WebViewAsPopup: NSObject, UIWebViewDelegate {
    // 把bg和webView改成实例属性,让实例持有它们
    private var bgView: UIView!
    private var webView: UIWebView!

    func showWebViewPopup(on controller: UIViewController) {
        // Popup background
        bgView = UIView()
        bgView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        bgView.layer.backgroundColor = UIColor.black.withAlphaComponent(0.5).cgColor

        // Webview sizing
        let width = UIScreen.main.bounds.width - 60
        let height = UIScreen.main.bounds.height - 200
        let x = UIScreen.main.bounds.width/2 - width/2
        let y = UIScreen.main.bounds.height/2 - height/2

        // Webview stuff
        webView = UIWebView()
        webView.frame = CGRect(x: x, y: y, width: width, height: height)
        webView.delegate = self // 现在设置代理不会崩溃了
        let url = URL(string: "https://google.com")!
        let request = URLRequest(url: url)
        webView.loadRequest(request)

        // Styling webview popup
        webView.layer.borderWidth = 1
        webView.layer.borderColor = UIColor.black.cgColor
        webView.layer.masksToBounds = true
        webView.layer.cornerRadius = 10

        // Add bg then webview to main view controller
        controller.view.addSubview(bgView)
        controller.view.addSubview(webView)
    }

    func webViewDidStartLoad(_ webView: UIWebView) {
        print("#webViewDidStartLoad!")
    }

    func webViewDidFinishLoad(_ webView: UIWebView) {
        print("#webViewDidFinishLoad!")
    }

    // 可选:加个移除弹窗的方法,方便后续扩展
    func dismissPopup() {
        bgView.removeFromSuperview()
        webView.removeFromSuperview()
    }
}

第二步:修改ViewController.swift,持有WebViewAsPopup实例

确保实例不会在方法结束后被ARC回收:

// ViewController.swift
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var showPopupBtn: UIButton!
    // 新增属性持有popup实例,防止被回收
    private var popup: WebViewAsPopup?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func showPopupTapped(_ sender: Any) {
        popup = WebViewAsPopup()
        popup?.showWebViewPopup(on: self)
    }
}

额外小贴士

苹果早就废弃了UIWebView,如果你的项目是新开发的,建议换成WKWebView——它性能更好,API也更现代。不过上面的修复方案完全适配你当前的代码,改完就能正常运行啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:14:36