iOS开发:以隐藏/显示视图控制器替代添加/移除至父控制器
实现方案:单次实例化+隐藏保留ViewController状态
兄弟,这个需求太典型了——尤其是WebView这种加载慢、需要保留状态的场景,完全不用每次都销毁重建,我给你两个靠谱的实现思路,优先推荐第一种,更符合iOS的控制器生命周期规范:
方案一:将VC B作为VC A的子控制器管理
这种方式是最规范的,把VC B当成VC A的子控制器来持有,通过控制它的view的显示/隐藏来实现需求,不会触发VC B的销毁生命周期。
步骤1:在VC A中声明全局的VC B实例
首先在VC A里定义一个仅初始化一次的VC B变量,确保整个应用生命周期里只有这一个实例:
// Swift 示例代码,OC 思路完全一致 class ViewControllerA: UIViewController { // 只初始化一次的 WebView 控制器实例 private var webViewController: ViewControllerB? override func viewDidLoad() { super.viewDidLoad() // 这里可以提前初始化,也可以等到第一次点击按钮时再初始化,看你需求 } }
步骤2:按钮点击的逻辑处理
点击按钮时,先判断VC B是否已经初始化:如果没初始化,就创建并添加为子控制器;如果已经存在,直接切换它的显示状态:
@IBAction func toggleWebVCButtonTapped(_ sender: UIButton) { guard let webVC = webViewController else { // 第一次初始化,仅执行一次 let newWebVC = ViewControllerB() // 添加为子控制器 addChild(newWebVC) newWebVC.view.frame = view.bounds // 铺满VC A的视图 view.addSubview(newWebVC.view) newWebVC.didMove(toParent: self) // 标记为已初始化,并显示 webViewController = newWebVC newWebVC.view.isHidden = false return } // 已经存在,切换显示/隐藏状态 webVC.view.isHidden = !webVC.view.isHidden }
关键注意点
- 绝对不要调用
removeFromParent()或者把webVC的view从父视图中移除,那样会触发VC B的deinit,导致WebView和状态被销毁。 - 如果需要在隐藏时节省资源,可以在设置
isHidden = true时调用webVC.webView.stopLoading(),显示时再恢复加载(可选操作,看你的需求)。
方案二:全局容器持有VC B实例(跨控制器复用场景)
如果VC B需要在多个控制器之间复用,而不只是VC A,你可以用一个全局的容器来持有它的实例,比如自定义一个ControllerManager单例:
class ControllerManager { static let shared = ControllerManager() // 全局唯一的 WebView 控制器实例 var webViewController: ViewControllerB? private init() {} // 保证单例 func getWebVC() -> ViewControllerB { if let existingVC = webViewController { return existingVC } let newVC = ViewControllerB() webViewController = newVC return newVC } }
然后在任何需要的地方调用ControllerManager.shared.getWebVC()来获取同一个实例,添加到当前控制器的子视图中,控制显示隐藏即可。不过这种方式要注意内存管理,确保不需要时可以手动置空(但你的需求是应用生命周期内保留,所以没问题)。
内容的提问来源于stack exchange,提问作者mefahimrahman
相关产品推荐
相关产品推荐

