自定义类中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
相关产品推荐
相关产品推荐

