导航栏返回按钮触发Unwind segue时如何向父控制器传值更新视图
实现方案
不用折腾给导航返回按钮加target、runtime方法交换这类野路子,iOS原生提供了多套适配方案,按使用优先级排序如下:
方案1:生命周期自动触发刷新(零耦合最简单)
如果只是需要回到VC1时刷新视图数据,完全不需要手动监听返回事件、也不需要写传值逻辑,直接在VC1内重写viewWillAppear即可——不管是点导航返回按钮、侧滑返回,只要VC1即将显示到屏幕上就会自动触发:
// ViewController1 内代码 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 在这里执行你的数据更新、UI刷新逻辑 reloadViewData() }
注意:如果VC1嵌在
UITabBarController中,切换标签页也会触发这个方法。如果需要区分「从VC2返回」的特定场景,配合下面的传值方案加标记位判断即可。
哪怕你的VC1是嵌在UIStackView、其他自定义容器里,这个生命周期方法也会正常触发,不受外层容器影响。
方案2:闭包/代理反向传值(最规范,适合需要带回VC2操作数据的场景)
如果需要把用户在VC2中操作产生的新数据传回VC1,用闭包(OC用block)或者代理实现反向传值是苹果推荐的标准写法,不需要监听返回动作:
- 先在VC2中定义传值回调
// ViewController2 内代码 class ViewController2: UIViewController { // 定义回调,参数替换为你实际需要传回的数据类型 var dataUpdateCallback: ((<#YourDataType#>) -> Void)? // 用户在VC2操作完成、触发返回时调用回调传值 func userDidCompleteOperation() { let newData = <#你要传回的实际数据#> dataUpdateCallback?(newData) navigationController?.popViewController(animated: true) } }
- 在VC1跳转至VC2的位置,设置回调接收逻辑
// ViewController1 跳转逻辑代码 @objc func jumpToVC2() { let vc2 = ViewController2() // 弱引用self避免循环引用 vc2.dataUpdateCallback = { [weak self] receivedData in guard let self = self else { return } // 在这里用收到的新数据更新UI self.updateUI(with: receivedData) } navigationController?.pushViewController(vc2, animated: true) }
方案3:导航控制器代理精准监听返回事件(特殊场景用)
如果你必须精准识别用户点击系统返回按钮的动作,直接遵守UINavigationControllerDelegate协议实现代理方法即可,不用自定义返回按钮:
// ViewController1 内代码 extension ViewController1: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 判断即将显示的控制器是当前VC1,且是从其他页面pop返回的 guard viewController == self, !navigationController.viewControllers.contains(where: { $0 is ViewController2 }) else { return } // 在这里执行返回时的专属逻辑 reloadViewData() } }
记得在VC1的viewDidLoad中设置代理:navigationController?.delegate = self
内容的提问来源于stack exchange,提问作者djdannel
相关产品推荐
相关产品推荐

