iOS中UINavigationController返回后如何调用ViewController1的方法?
解决方法:让ViewController1从ViewController2返回时自动执行方法
不用UINavigationControllerDelegate的话,有几个更轻量的方案,你可以根据需求选择:
1. 利用ViewController的生命周期方法(最简单,无需修改VC2)
viewWillAppear(_:) 或 viewDidAppear(_:) 会在ViewController被显示时触发,自然也包括从VC2 pop回来的场景。唯一要注意的是首次加载VC1时也会触发,所以加个标记区分即可:
class ViewController1: UIViewController { // 标记是否是首次加载页面 private var isFirstAppearance = true override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if !isFirstAppearance { // 这里写从VC2返回后要执行的操作 performPostReturnAction() } // 首次加载完成后,把标记设为false isFirstAppearance = false } private func performPostReturnAction() { print("从VC2回来了,执行预设操作!") // 你的业务逻辑代码写在这里 } }
这个方案零额外依赖,只需要在VC1里加几行代码,非常省心。
2. 闭包回调(最精准,可控性强)
如果希望只有在从VC2返回时才触发(避免其他场景误触发),可以给VC2加一个回调闭包,在它即将被pop时调用:
首先在ViewController2里定义闭包:
class ViewController2: UIViewController { // 定义回调闭包,用weak避免循环引用风险 var onWillPop: (() -> Void)? override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 判断当前是否是被从导航栈中移除(也就是执行了pop操作) if isMovingFromParent { onWillPop?() } } // 如果是自己手动调用pop的方法,也可以直接在pop前触发闭包 @objc private func manualPop() { navigationController?.popViewController(animated: true) onWillPop?() } }
然后在ViewController1 push VC2时,设置这个闭包:
class ViewController1: UIViewController { private func pushToVC2() { let vc2 = ViewController2() // 用[weak self]避免循环引用 vc2.onWillPop = { [weak self] in self?.performPostReturnAction() } navigationController?.pushViewController(vc2, animated: true) } private func performPostReturnAction() { print("从VC2回来了,执行预设操作!") // 你的业务逻辑代码写在这里 } }
这个方案的好处是完全可控,只有当VC2被pop时才会触发,不会被其他显示场景干扰。
3. NotificationCenter通知(适合跨多层页面的场景)
如果VC1和VC2之间隔了多层导航,或者需要全局监听返回事件,可以用通知:
在ViewController1里注册通知:
class ViewController1: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 注册通知监听 NotificationCenter.default.addObserver( self, selector: #selector(handleReturnFromVC2), name: NSNotification.Name("ReturnedFromVC2"), object: nil ) } @objc private func handleReturnFromVC2() { performPostReturnAction() } private func performPostReturnAction() { print("从VC2回来了,执行预设操作!") } // 记得在页面销毁时移除监听,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self) } }
在ViewController2里发送通知:
class ViewController2: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParent { // 发送返回通知 NotificationCenter.default.post( name: NSNotification.Name("ReturnedFromVC2"), object: nil ) } } }
不过这个方案是全局通知,不如闭包精准,除非必要,优先选前两种。
内容的提问来源于stack exchange,提问作者Mark Meretzky
相关产品推荐
相关产品推荐

