UIViewControllerTransitioningDelegate异常:present动画失效但dismiss正常
解决模态ViewController自定义转场动画的代理时机问题
问题分析
你遇到的核心问题是transitioningDelegate的赋值时机错误,导致UIKit无法正确读取自定义转场逻辑:
- 在
init()中设置:如果你的模态VC是通过Storyboard/XIB初始化的,init()方法根本不会被触发(此时调用的是init?(coder:)),代理完全没被设置,所以present动画无效果。 - 在
viewDidLoad()中设置:此时模态VC的present流程已经启动,UIKit已经用默认转场逻辑处理了present动画,只有dismiss时代理已生效,所以dismiss动画符合预期。
解决方案
正确的做法是在初始化模态VC之后、调用present(_:animated:completion:)之前,在外部设置它的transitioningDelegate,同时配置正确的模态展示样式:
外部提前设置代理
在发起present的VC中执行以下逻辑:// 初始化模态VC(代码或Storyboard方式均可) let modalVC = YourModalViewController() // 关键步骤:在present前设置转场代理 modalVC.transitioningDelegate = self // 必须设置为.custom,否则自定义转场会被忽略 modalVC.modalPresentationStyle = .custom // 发起present操作 present(modalVC, animated: true)确保转场代理方法正确实现
代理类(推荐用发起present的VC,也可复用模态VC自身)需要实现以下核心方法:extension YourPresentingViewController: UIViewControllerTransitioningDelegate { // 返回自定义present动画器 func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return CustomPresentAnimator() // 你的自定义present动画类 } // 返回自定义dismiss动画器 func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return CustomDismissAnimator() // 你的自定义dismiss动画类 } // 若需自定义overlay背景,返回自定义PresentationController func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return OverlayPresentationController(presentedViewController: presented, presenting: presenting) } }修复overlayView的动画逻辑
针对你需要的alpha过渡需求,在自定义OverlayPresentationController中处理:class OverlayPresentationController: UIPresentationController { private let overlayView = UIView() override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) { super.init(presentedViewController: presentedViewController, presenting: presentingViewController) overlayView.backgroundColor = .black } override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() overlayView.frame = containerView?.bounds ?? .zero overlayView.alpha = 0 containerView?.addSubview(overlayView) // 配合转场协调器执行alpha动画 presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in self.overlayView.alpha = 0.65 }) } override func dismissalTransitionWillBegin() { super.dismissalTransitionWillBegin() // dismiss时反向过渡alpha presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in self.overlayView.alpha = 0 }) } }
关键注意点
- 绝对不要在模态VC内部的生命周期方法中设置
transitioningDelegate,必须在present操作前完成赋值。 - 自定义转场必须将
modalPresentationStyle设为.custom,否则UIKit会直接使用默认转场逻辑。 - 如果通过Storyboard实例化模态VC,要在
instantiateViewController(withIdentifier:)之后立即设置代理和展示样式。
内容的提问来源于stack exchange,提问作者Another Dude
相关产品推荐
相关产品推荐

