如何在两个ViewController间复用loadWebView与loadURL方法?
解决ViewController间WebView代码复用的问题
你遇到的问题核心是直接实例化另一个ViewController调用其方法会导致视图生命周期和属性归属混乱——PrivacyPolicyController的webView是绑定在它自己的视图层级里的,你在TermsAndConditionsController里创建它的实例调用方法,不仅webView不会挂载到当前VC的view上,还可能因为另一个VC的生命周期未正确触发,导致webView为nil从而引发崩溃。
最合理的解决方案是把公共的WebView逻辑提取到一个基类ViewController中,让需要用到这些功能的VC都继承这个基类,这样就能完美复用代码了。下面是具体的实现步骤:
步骤1:创建WebView基类
新建一个继承自UIViewController并遵循WKUIDelegate的基类,把loadWebView、loadURL以及webView属性都放在这里:
import UIKit import WebKit class WebBaseViewController: UIViewController, WKUIDelegate { var webView: WKWebView! override func loadView() { super.loadView() // 初始化WebView并设置为当前VC的view loadWebView() } func loadWebView() { let webConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self view = webView } func loadURL(url: String) { guard let myURL = URL(string: url) else { print("Invalid URL: \(url)") return } let myRequest = URLRequest(url: myURL) webView.load(myRequest) } }
步骤2:修改PrivacyPolicyController继承基类
原来的PrivacyPolicyController只需要继承这个基类,然后在viewDidLoad里加载对应的URL即可:
import UIKit import WebKit class PrivacyPolicyController: WebBaseViewController { override func viewDidLoad() { super.viewDidLoad() loadURL(url: "https://www.apple.com") } }
步骤3:修改TermsAndConditionsController继承基类
同样的,TermsAndConditionsController继承基类后,直接调用loadURL加载你需要的条款链接:
import UIKit import WebKit class TermsAndConditionsController: WebBaseViewController { override func viewDidLoad() { super.viewDidLoad() // 替换成你的条款页面URL loadURL(url: "https://www.example.com/terms") } }
为什么之前的方法不行?
- 直接创建ViewController对象调用方法:
PrivacyPolicyController的webView属于它自己的视图,和TermsAndConditionsController的view没有任何关联,而且这个实例的生命周期没有被系统正确管理(比如loadView没被调用),导致webView未初始化,调用loadURL时就会因为webView为nil崩溃。 - 扩展UIViewController:你之前尝试扩展可能没有正确处理
webView的初始化和视图绑定,因为每个VC的view都是独立的,直接扩展会导致多个VC共享同一个webView实例(如果属性定义在扩展里),或者无法正确挂载到当前VC的视图层级。
这样修改后,两个VC都能复用WebView的初始化和加载逻辑,而且各自的视图生命周期都能正常工作,不会出现崩溃问题。
内容的提问来源于stack exchange,提问作者sk123
相关产品推荐
相关产品推荐

