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

连续点击按钮触发转场动画时App崩溃,报错子控制器需同属父控制器

问题分析与解决方案

崩溃原因

连续点击按钮时,前一次转场动画的completion回调尚未执行,视图控制器的父子关系处于未完全更新的中间状态。此时再次调用transition(from:to:...)方法,会导致参与转场的两个视图控制器不满足"拥有共同父视图控制器"的要求,从而触发NSInvalidArgumentException异常。缩短动画时长时,completion回调会更快执行,父子关系及时更新,因此不会崩溃,但动画体验变差。

修复方案

核心思路是禁止在转场动画进行中触发新的转场,通过添加状态锁避免并发执行转场逻辑,同时修正视图控制器父子关系的处理流程:

  1. 添加转场状态标记
    在当前控制器中增加私有属性,标记是否正在执行转场:
private var isPerformingTransition = false
  1. 修改转场方法逻辑
    更新transitionBetweenViews方法,加入状态判断,并规范视图控制器的父子关系处理:
func transitionBetweenViews() {
    // 防止连续触发转场动画
    guard !isPerformingTransition else { return }
    isPerformingTransition = true
    
    let fromViewController = aController
    let toViewController = bController
    let options: UIView.AnimationOptions = self.viewModel.State == .something ? .transitionFlipFromRight : .transitionFlipFromLeft
    
    // 处理目标视图控制器的添加逻辑:若尚未成为子VC则完成添加流程
    if !self.children.contains(toViewController) {
        addChild(toViewController)
        containerView.fillWithView(toViewController.view)
        toViewController.didMove(toParent: self)
    }
    
    // 标记源视图控制器即将被移除
    fromViewController.willMove(toParent: nil)
    
    self.transition(from: fromViewController, to: toViewController, duration: 0.5, options: options, animations: nil, completion: { [weak self] _ in
        guard let self = self else { return }
        // 完成源视图控制器的移除
        fromViewController.removeFromParent()
        // 重置转场标记,允许下次触发
        self.isPerformingTransition = false
    })
}

额外注意事项

  • 确保aController和bController的引用始终指向正确的视图控制器实例,避免出现引用失效或错误的情况。
  • 转场过程中涉及的视图容器containerView需保证布局正确,避免视图层级混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:35:14