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

iOS模拟器慢动作模式下UIViewControllerAnimatedTransitioning动画为何无法结束?

解决慢动作模式下自定义转场完成回调不触发的问题

嘿,这个问题我之前调试自定义转场时也踩过坑,简直是让人头大的bug!当模拟器开启慢动作模式时,转场动画卡住、UI失去响应,本质是因为转场上下文的completeTransition(_:)方法没有被正确调用,导致UIKit无法结束转场流程。

问题根源

系统的慢动作模式会将所有UI动画的播放速度降低(通常是0.1倍速),但如果你的转场实现存在以下问题,就会导致回调丢失:

  • 动画块使用的时长和transitionDuration(using:)返回的时长不一致,UIKit无法同步转场进度
  • 使用了Core Animation的底层API(如CAAnimation)但没有正确监听动画结束事件
  • 动画完成回调中没有处理转场取消的情况,或者遗漏了调用completeTransition(_:)

正确的实现示例

下面是一个修复后的UIViewControllerAnimatedTransitioning实现,专门适配慢动作模式:

class CustomTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    
    // 统一管理转场时长,动画块必须复用这个值
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        // 先做安全校验,避免因获取不到视图/控制器导致卡住
        guard let fromVC = transitionContext.viewController(forKey: .from),
              let toView = transitionContext.view(forKey: .to) else {
            transitionContext.completeTransition(false)
            return
        }
        
        let containerView = transitionContext.containerView
        let duration = transitionDuration(using: transitionContext)
        
        // 添加目标视图到容器
        containerView.addSubview(toView)
        // 设置初始动画状态
        toView.alpha = 0.0
        toView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
        
        // 使用UIKit封装的动画块,它会自动处理慢动作模式下的时长同步
        UIView.animate(withDuration: duration, delay: 0, options: .curveEaseInOut) {
            toView.alpha = 1.0
            toView.transform = .identity
            fromVC.view.alpha = 0.6
        } { [weak self] finished in
            // 恢复原视图状态,避免影响后续转场
            fromVC.view.alpha = 1.0
            // 必须调用completeTransition,传入转场是否被取消的反向值
            let wasCancelled = transitionContext.transitionWasCancelled
            transitionContext.completeTransition(!wasCancelled)
        }
    }
}

额外调试技巧

  • 如果必须使用Core Animation的CAAnimation,一定要设置代理并在animationDidStop(_:finished:)中调用completeTransition(_:),确保动画结束事件被正确捕获
  • 在completeTransition(_:)前后添加打印日志,确认该方法是否被触发,方便定位问题
  • 不要手动修改动画的speed属性,让UIKit自动处理慢动作模式下的动画速度调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:00:35