Swift:iOS13及以上版本中如何处理视图控制器的交互式关闭?
解决iOS13+模态控制器交互式关闭的专属处理方案
这个场景我太熟悉了,用viewWillDisappear或viewDidDisappear确实会踩坑——只要push子控制器就触发,根本没法区分是子页面弹出还是当前模态被关闭。针对iOS13及以上的交互式模态关闭,苹果其实提供了专门的代理方法来处理,完全能满足你的需求:
核心方案:利用UIAdaptivePresentationControllerDelegate
这个代理是iOS13新增的,专门用来处理自适应模态的相关事件,其中的presentationControllerDidDismiss方法只会在当前模态控制器被真正dismiss时触发——不管是用户下拉交互式关闭,还是主动调用dismiss(_:)方法,都能精准捕获;而push子控制器时绝对不会触发,完美避开你的痛点。
具体实现步骤
- 让你的视图控制器遵守协议:
class YourModalVC: UIViewController, UIAdaptivePresentationControllerDelegate { // 你的控制器原有代码 }
- 在
viewDidLoad中绑定代理:
override func viewDidLoad() { super.viewDidLoad() // 给presentationController设置代理 presentationController?.delegate = self }
- 实现专属的关闭处理逻辑:
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { // 在这里执行你需要的特定操作 print("模态控制器被交互式关闭/主动关闭了") // 比如更新父页面数据、清理临时资源等 }
额外拓展:控制是否允许交互式关闭
如果你需要在某些场景下阻止用户交互式关闭(比如表单未填写完成),可以实现另一个代理方法:
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { // 根据业务逻辑返回true(允许关闭)或false(阻止关闭) return isFormCompleted() // 示例:表单验证通过才允许关闭 }
补充说明
如果需要区分是用户交互式关闭还是代码主动调用dismiss,可以通过标记位实现:比如主动调用dismiss前设置isManuallyDismissed = true,在presentationControllerDidDismiss里判断这个标记,执行对应逻辑后再重置标记。
内容的提问来源于stack exchange,提问作者Sotiris Kaniras
相关产品推荐
相关产品推荐

