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

使用modalPresentationStyle = .overCurrentContext后屏幕冻结问题求助

问题排查与解决方案

核心原因

  1. 重复执行dismiss操作:你同时调用了self.controller?.dismiss(animated: true)和self.nvc?.dismiss(animated: true),但实际上只需要dismiss被present出来的根控制器(也就是nvc)即可,重复dismiss会导致UI线程的动画队列混乱,引发冻结。
  2. viewDidLoad中立即push的时序问题:在FirstViewController的viewDidLoad里直接push到SecondViewController,此时导航控制器的present动画还未完成,连续的导航栈动画+present动画会导致UIKit的动画系统冲突,埋下冻结隐患。

修复步骤

1. 移除重复的dismiss调用

只需要保留对目标控制器的单次dismiss操作,修改第4步的代码:

// 直接调用当前控制器的dismiss即可,无需同时调用两个
self.dismiss(animated: true, completion: nil)
// 或者持有nvc引用时,也可以用:
// self.nvc?.dismiss(animated: true, completion: nil)

2. 调整push的执行时机

把FirstViewController中push到SecondViewController的操作从viewDidLoad移到viewDidAppear中,确保present动画完成后再执行push,同时避免重复触发:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    guard let nav = navigationController else { return }
    if nav.topViewController is FirstViewController {
        showSecondViewController(parentController: nav)
    }
}

3. 优化pop与dismiss的时序

在SecondViewController的pop操作中,添加completion回调,确认pop完成后再触发dismiss,避免动画叠加冲突:

// 修改pop操作,增加完成回调
navigationController?.popViewController(animated: animated) { [weak self] in
    self?.dismissModal()
}

// 单独封装dismiss逻辑
private func dismissModal() {
    self.dismiss(animated: true, completion: nil)
}

验证要点

  • 确保整个流程中只有一次dismiss操作,针对被present的根导航控制器
  • 所有导航栈操作(push/pop)都在present动画完成后执行,避免动画冲突
  • 使用weak self避免循环引用,防止内存泄漏间接导致的UI冻结

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:27:26