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

如何让子UIViewController dismiss后触发父控制器completion handler

实现子控制器dismiss后触发父控制器回调的方案

首先明确:present(_:animated:completion:) 方法传入的completion闭包,触发时机是present动画执行完毕、子控制器完全展示在顶层时,和子控制器后续的dismiss操作无关,你之前的预期和UIKit的实际设计不符。

你可以根据项目的最低支持版本,选下面两种成熟方案实现需求:

方案1:iOS 15+ 原生无侵入方案(推荐)

iOS 15 开始系统提供了专门的dismiss完成回调,不需要修改子控制器的代码,只要在父控制器中遵守UIAdaptivePresentationControllerDelegate协议,实现对应方法即可:

// 父控制器中present子控制器的代码
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // 数据缺失判断逻辑
    if 数据缺失 {
        let myUpload = UploadInv()
        myUpload.modalPresentationStyle = = .fullScreen
        myUpload.modalTransitionStyle = .flipHorizontal
        // 绑定代理
        myUpload.presentationController?.delegate = self

        x += 1
        // 这里不需要传present的completion,除非你要处理present完成的逻辑
        self.present(myUpload, animated: true)
    }
}

// 实现代理回调,子控制器dismiss动画完成后会自动触发
extension 你的父控制器类名: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        print("\(x)")
        // 在这里写dismiss完成后要执行的业务逻辑,比如刷新数据、读取子控制器回传的内容
    }
}

这个回调对所有dismiss场景生效:不管是子控制器主动调用dismiss方法关闭,还是用户通过下拉手势关闭模态页,都会在dismiss动画完全结束后触发,时机准确。

方案2:自定义闭包属性(兼容全系统版本,可控性最高)

如果需要支持iOS15以下的系统版本,直接用经典的闭包逆传方案即可,逻辑完全可控,还可以通过闭包参数直接回传子控制器采集到的业务数据:

  1. 首先在子控制器UploadInv中定义回调属性,在自身dismiss完成时触发闭包:
class UploadInv: UIViewController {
    // 定义dismiss完成回调,可根据业务需要加参数,比如 var onDismissComplete: ((UploadData) -> Void)?
    var onDismissComplete: (() -> Void)?

    // 子控制器中触发关闭的逻辑(比如关闭按钮点击方法)
    @objc private func closeAction() {
        self.dismiss(animated: true) { [weak self] in
            // dismiss动画完成后再调用回调,保证时机准确
            self?.onDismissComplete?()
        }
    }
}
  1. 在父控制器present子控制器时,给回调属性赋值即可:
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // 数据缺失判断逻辑
    if 数据缺失 {
        let myUpload = UploadInv()
        myUpload.modalPresentationStyle = .fullScreen
        myUpload.modalTransitionStyle = .flipHorizontal

        x += 1
        // 绑定dismiss完成回调
        myUpload.onDismissComplete = { [weak self] in
            guard let self = self else { return }
            print("\(self.x)")
            // 执行后续业务逻辑
        }

        self.present(myUpload, animated: true)
    }
}

避坑提示

  • 你贴的测试代码有个笔误:前面实例化的变量名是myUp,后面配置属性的时候用了myUpload,实际运行会触发未声明标识符的编译错误,记得统一变量名。
  • 不要尝试通过重写父控制器的dismiss(animated:completion:)方法监听关闭事件,子控制器调用dismiss时系统会自动沿控制器层级转发事件,很容易出现时机提前、重复触发的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:48:28