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
相关产品推荐
相关产品推荐

