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

模态关闭子ViewController后父ViewController完全重载的异常问题

解决模态关闭后父视图控制器意外重载的问题

这种情况我之前也踩过坑,大概率是父VC的生命周期方法触发了全量刷新,或者子VC对父VC的引用不当导致的。下面给你几个排查和解决的具体方向:

1. 检查父VC的viewWillAppear(_:)方法

很多开发者习惯把数据加载、tableView.reloadData()这类逻辑放在viewWillAppear里,但模态关闭时父VC的viewWillAppear会被系统自动调用——如果这里写了全量刷新,就会导致整个VC重载。

解决办法:

  • 把一次性的初始化、全量加载逻辑移到viewDidLoad里,这个方法只会在VC创建时执行一次。
  • 如果确实需要在viewWillAppear里更新内容,加个判断条件,比如用一个标记变量控制只有必要时才刷新:
    private var isFirstLoad = true
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if isFirstLoad {
            loadInitialData()
            tableView.reloadData()
            isFirstLoad = false
        }
        // 或者只在子VC返回后需要更新时才刷新(结合下面的代理/闭包方案)
    }
    

2. 替换子VC对父VC的强引用,改用代理/闭包模式

你提到子VC持有父VC的引用,这种强引用不仅容易造成循环引用内存泄漏,还可能不小心触发父VC的刷新逻辑。更合理的做法是用代理模式或者闭包回调来传递子VC的结束事件,而不是让子VC直接操作父VC。

示例:代理模式实现

子VC代码:

// 定义代理协议
protocol CollectionPicturesDelegate: AnyObject {
    func didFinishPictureSelection()
}

class CollectionPicturesViewController: UIViewController {
    // 用weak避免循环引用
    weak var delegate: CollectionPicturesDelegate?

    // 假设关闭按钮的点击事件
    @IBAction func closeButtonTapped(_ sender: UIButton) {
        dismiss(animated: true) {
            // 通知父VC操作完成
            self.delegate?.didFinishPictureSelection()
        }
    }
}

父VC代码:

class NewAdCreationViewController: UIViewController, CollectionPicturesDelegate {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == picturesCollectionVCSegueName {
            let navController = segue.destination as! UINavigationController
            let collectionController = navController.viewControllers.first as! CollectionPicturesViewController
            // 设置代理,替代直接持有父VC引用
            collectionController.delegate = self
        }
    }

    // 实现代理方法,按需刷新
    func didFinishPictureSelection() {
        // 不要全量reloadData,只刷新需要更新的行
        tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
    }
}

3. 检查子VC的dismiss逻辑

如果子VC在关闭时,不小心调用了父VC的刷新方法(比如parentVC.tableView.reloadData()),也会导致父VC重载。检查子VC中dismiss的代码,移除不必要的父VC操作。

4. 排查Segue设置

虽然可能性较低,但可以确认下Storyboard里的Segue类型:确保是Modal展示,Presentation属性不要设成会替换父VC的类型(比如"Full Screen"是正常的模态类型)。

另外注意:如果之前子VC持有父VC的强引用,记得清理掉,避免内存泄漏——代理模式里用weak var就是为了这个目的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:46:54