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

Swift中NavigationController返回时如何正确设置父控制器变量?

iOS从B控制器返回A控制器传递数据的正确姿势

嘿,你遇到的这个问题其实是导航控制器代理方法的触发时机搞的鬼——当从B返回A时,navigationController(_:willShow:animated:)的执行时机晚于A的viewWillAppear,所以A在viewWillAppear里根本拿不到B刚传过来的数据,自然number还是初始的-1。

给你推荐两种靠谱的解决办法,优先选第一种,逻辑更清晰:

方法一:闭包回调(推荐)

这种方式是iOS开发里返回传值的常用操作,完全避开时机问题,还能降低控制器之间的耦合度。

步骤1:在B控制器里定义回调闭包

class Bcontroller: UIViewController {
    // 定义回调闭包,参数就是你要传递的两个值
    var backToACallback: ((Int, Bool) -> Void)?
    
    // 假设这是你要传递的数据源
    var numberInB = 100
    var boolInB = true
    
    // 如果你用的是自定义返回按钮,就在点击事件里触发回调
    @IBAction func customBackTapped(_ sender: UIButton) {
        // 触发回调,把数据传回去
        backToACallback?(numberInB, boolInB)
        navigationController?.popViewController(animated: true)
    }
    
    // 如果用的是系统默认返回按钮,拦截返回事件触发回调
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        // 当parent为nil时,说明当前控制器要被弹出栈了
        if parent == nil {
            backToACallback?(numberInB, boolInB)
        }
    }
}

步骤2:在A控制器跳转时设置回调

class Acontroller: UIViewController {
    var number = -1
    var myBoolean = false
    
    // 跳转到B控制器的方法
    func goToB() {
        let bVC = Bcontroller()
        // 设置回调,接收B传回来的数据
        bVC.backToACallback = { [weak self] receivedNum, receivedBool in
            guard let self = self else { return }
            self.number = receivedNum
            self.myBoolean = receivedBool
            // 这里可以直接处理数据,不用等viewWillAppear
            print(receivedBool)
        }
        navigationController?.pushViewController(bVC, animated: true)
    }
    
    // 如果你还是要在viewWillAppear里处理数据,现在数据已经提前设置好了
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if number != -1 {
            print(myBoolean)
        }
    }
}

⚠️ 注意:闭包里一定要加[weak self],不然会导致A控制器被循环引用,无法正常释放。

方法二:调整导航代理的时机(不推荐)

如果你坚持想用导航控制器的代理方法,可以把willShow换成didShow,同时把A里的逻辑移到viewDidAppear里:

修改B控制器的代理方法

extension Bcontroller: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        (viewController as? Acontroller)?.number = numberInB
        (viewController as? Acontroller)?.myBoolean = boolInB
    }
}

修改A控制器的生命周期方法

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if number != -1 {
        print(myBoolean)
    }
}

这种方式虽然能解决问题,但耦合度高,而且依赖导航控制器的代理,不如闭包灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:39:03