如何在被present的ViewController dismiss后调用MainViewController指定方法?
我来给你几个靠谱的解决方案,完美适配你这个场景:
方案1:使用闭包(Completion Handler)推荐
这是最直接可控的方式,完全不会出现viewWillAppear/viewDidAppear那种多次触发的问题,逻辑也清晰。
首先在被present的ViewController里定义一个闭包属性:
class PresentedViewController: UIViewController { // 定义闭包,用来通知主VC执行后续操作 var onDismissCompletion: (() -> Void)? // 用户触发操作的方法(比如按钮点击) @IBAction func userActionTapped(_ sender: UIButton) { // 先dismiss当前VC,在完成回调里触发闭包 dismiss(animated: true) { [weak self] in self?.onDismissCompletion?() } } }
然后在MainViewController里present这个VC时,绑定闭包到你要执行的方法:
class MainViewController: UIViewController { func presentMyViewController() { let presentedVC = PresentedViewController() // 绑定闭包,指定要执行的目标方法 presentedVC.onDismissCompletion = { [weak self] in self?.presentNewViewController() } present(presentedVC, animated: true) } // 你需要执行的目标方法 func presentNewViewController() { let newVC = UIViewController() newVC.view.backgroundColor = .blue present(newVC, animated: true) } }
注意用[weak self]避免循环引用,闭包只会在dismiss完全完成后执行一次,精准符合你的需求。
方案2:使用代理模式(Delegate Pattern)
如果你的业务逻辑比较复杂,或者这个PresentedViewController需要和多个VC交互,代理模式会让代码结构更规范清晰。
首先定义代理协议:
protocol PresentedViewControllerDelegate: AnyObject { func presentedViewControllerDidFinish(_ vc: PresentedViewController) }
然后在PresentedViewController里添加代理属性:
class PresentedViewController: UIViewController { // 用weak避免循环引用 weak var delegate: PresentedViewControllerDelegate? @IBAction func userActionTapped(_ sender: UIButton) { dismiss(animated: true) { [weak self] in guard let self = self else { return } self.delegate?.presentedViewControllerDidFinish(self) } } }
接下来让MainViewController遵守这个代理协议:
class MainViewController: UIViewController, PresentedViewControllerDelegate { func presentMyViewController() { let presentedVC = PresentedViewController() presentedVC.delegate = self present(presentedVC, animated: true) } // 实现代理方法,触发目标操作 func presentedViewControllerDidFinish(_ vc: PresentedViewController) { presentNewViewController() } func presentNewViewController() { let newVC = UIViewController() newVC.view.backgroundColor = .blue present(newVC, animated: true) } }
代理模式的好处是耦合度低,逻辑分工明确,适合中大型项目的场景。
方案3:通知机制(Notification)如果一定要用的话
你担心MainViewController接收不到通知?其实只要正确注册和移除通知,完全没问题——毕竟是MainVC present的这个VC,dismiss的时候MainVC肯定还在内存中,能正常收到通知。
首先定义一个专属的通知名称:
extension Notification.Name { static let presentedVCDismissed = Notification.Name("presentedVCDismissed") }
在MainViewController里注册通知,记得在销毁时移除:
class MainViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 注册通知,绑定到目标方法 NotificationCenter.default.addObserver(self, selector: #selector(presentNewViewController), name: .presentedVCDismissed, object: nil) } deinit { // 移除通知,避免野指针问题 NotificationCenter.default.removeObserver(self) } func presentMyViewController() { let presentedVC = PresentedViewController() present(presentedVC, animated: true) } @objc func presentNewViewController() { let newVC = UIViewController() newVC.view.backgroundColor = .blue present(newVC, animated: true) } }
最后在PresentedViewController里dismiss完成后发送通知:
class PresentedViewController: UIViewController { @IBAction func userActionTapped(_ sender: UIButton) { dismiss(animated: true) { // 发送通知 NotificationCenter.default.post(name: .presentedVCDismissed, object: nil) } } }
不过这个方案的缺点是耦合度高,通知是全局的,如果多个地方注册同名通知容易出问题,所以优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者user3239711
相关产品推荐
相关产品推荐

