如何在另一个UIView中触发ViewController的dismiss操作
实现方案
下面提供3种常用的实现方式,可根据你的项目场景选择:
方案1:通过响应者链直接查找ViewController(无额外耦合,快速实现)
利用iOS响应者链机制,沿视图层级向上查找当前所属的ViewController,直接调用dismiss即可:
@objc func cancelButtonTapped() { var nextResponder = self.next while let responder = nextResponder { if let vc = responder as? UIViewController { vc.dismiss(animated: true) break } nextResponder = responder.next } }
方案2:闭包回调(耦合低、灵活度高,推荐常用场景)
在自定义View中暴露回调闭包,由持有该View的ViewController实现dismiss逻辑:
- 首先在你的自定义UIView类中定义回调属性:
// 自定义UIView类内部 var cancelButtonTappedCallback: (() -> Void)?
- 补全按钮点击方法,触发回调:
@objc func cancelButtonTapped() { cancelButtonTappedCallback?() }
- 在初始化该自定义View的ViewController中,实现闭包逻辑:
// ViewController 中初始化自定义View的位置 let customView = YourCustomView() customView.cancelButtonTappedCallback = { [weak self] in self?.dismiss(animated: true) // 如果是push出来的页面,替换为下面的代码 // self?.navigationController?.popViewController(animated: true) }
方案3:代理模式
和闭包逻辑类似,通过代理协议传递点击事件:
- 定义代理协议:
protocol CustomViewActionDelegate: AnyObject { func didTriggerCancelAction() }
- 自定义View中添加代理属性,点击时调用代理方法:
// 自定义UIView类内部 weak var delegate: CustomViewActionDelegate? @objc func cancelButtonTapped() { delegate?.didTriggerCancelAction() }
- ViewController遵守协议,实现代理方法:
extension YourViewController: CustomViewActionDelegate { func didTriggerCancelAction() { dismiss(animated: true) } } // 初始化View时设置代理 let customView = YourCustomView() customView.delegate = self
注意事项:如果当前ViewController是UINavigationController push进来的,需要把
dismiss(animated: true)替换为navigationController?.popViewController(animated: true);使用闭包/代理时要加[weak self]避免循环引用。
内容的提问来源于stack exchange,提问作者Begbie
相关产品推荐
相关产品推荐

