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

从‘Over Current Context’视图控制器返回时如何触发指定代码?

解决Over Current Context模态返回时触发指定代码的问题

这个问题我之前也碰到过,其实根源在于Over Current Context的展示特性——这种方式下,原来的ViewController的视图根本没被隐藏,所以系统不会触发viewWillAppear方法。下面给你几个实用的解决办法,选哪个看你的场景:


方法一:闭包回调(简单直接,适合轻量场景)

这种方式代码量最少,适合只需要简单传递回调的情况:

  1. 先在ViewController2里定义一个闭包属性:
class ViewController2: UIViewController {
    // 定义可选闭包,用于返回时的回调
    var onDismiss: (() -> Void)?
    
    @IBAction func close(_ sender: Any) {
        self.dismiss(animated: true) {
            // 在dismiss动画完成后调用闭包
            self.onDismiss?()
        }
    }
}
  1. 在ViewController跳转前设置闭包内容:
class ViewController: UIViewController {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let vc2 = segue.destination as? ViewController2 {
            // 给闭包赋值,写你要触发的代码
            vc2.onDismiss = {
                print("回到ViewController了,执行指定操作")
                // 比如刷新数据、更新UI之类的逻辑都可以放这里
            }
        }
    }
    
    // 原有的viewWillAppear代码(注意你之前写错了,应该调用super.viewWillAppear而不是super.viewDidAppear)
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("will appear")
    }
}

方法二:代理模式(结构清晰,适合复杂交互)

如果后续可能需要扩展更多回调逻辑,代理模式会更规范:

  1. 先定义一个代理协议:
// 定义代理协议,方法用于通知ViewController返回事件
protocol ViewController2Delegate: AnyObject {
    func viewController2DidFinishDismiss()
}
  1. 在ViewController2里添加代理属性:
class ViewController2: UIViewController {
    // 用weak避免循环引用
    weak var delegate: ViewController2Delegate?
    
    @IBAction func close(_ sender: Any) {
        self.dismiss(animated: true) {
            // 通知代理执行回调
            self.delegate?.viewController2DidFinishDismiss()
        }
    }
}
  1. 让ViewController遵守协议并设置代理:
class ViewController: UIViewController, ViewController2Delegate {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let vc2 = segue.destination as? ViewController2 {
            vc2.delegate = self
        }
    }
    
    // 实现代理方法,写要触发的代码
    func viewController2DidFinishDismiss() {
        print("通过代理触发回调,执行操作")
    }
}

方法三:通知中心(适合跨页面的全局回调)

如果你的回调需要通知多个页面,或者不想直接耦合两个ViewController,可以用通知:

  1. 在ViewController里注册并监听通知:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册通知,监听ViewController2的返回事件
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleVC2Dismiss),
            name: NSNotification.Name("ViewController2Dismissed"),
            object: nil
        )
    }
    
    @objc func handleVC2Dismiss() {
        // 这里写要触发的代码
        print("收到通知,执行指定操作")
    }
    
    // 记得在页面销毁时移除通知,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}
  1. 在ViewController2的返回方法里发送通知:
class ViewController2: UIViewController {
    @IBAction func close(_ sender: Any) {
        self.dismiss(animated: true) {
            // 发送通知
            NotificationCenter.default.post(
                name: NSNotification.Name("ViewController2Dismissed"),
                object: nil
            )
        }
    }
}

内容的提问来源于stack exchange,提问作者CL So

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:52:20