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

iOS 12系统下self.dismiss方法失效高版本运行正常的原因及修复方案

问题原因

  • 首先是代码中动画块的写法存在错误:UIView.animate的animations闭包本身默认在主队列执行,你额外套了一层DispatchQueue.main.async,会导致stackView的frame修改没有被当前动画块捕获,动画块因为没有可执行的属性动画,在iOS 12下会立刻触发completion回调,此时你异步派发的frame修改才刚要执行,视图上存在未完成的动画。
  • iOS 12的UIKit存在已知行为:当视图控制器的视图上有正在进行的未完成动画时,调用dismiss(animated: true)会被系统静默忽略,不会执行dismiss逻辑也不会触发completion回调。而iOS 13及以上版本对该场景做了兼容优化,会自动处理未完成动画后执行dismiss,所以你的代码在高版本系统可以正常运行。
  • 附加问题:你在动画completion闭包中直接强引用self调用dismiss,虽然不是本次问题的直接诱因,但存在循环引用风险。

修复方案

  1. 移除animations闭包里冗余的DispatchQueue.main.async包裹,确保frame修改被动画块正常捕获,动画执行时序正常:
UIView.animate(withDuration: 0.3, animations: { [weak self] in
    guard let self = self else { return }
    // 移除多余的主队列异步派发,直接修改frame
    self.stackViewMain.frame = CGRect(origin: CGPoint(x: self.stackViewMain.frame.origin.x, y: self.view.bounds.height), size: self.stackViewMain.bounds.size)
}) { [weak self] _ in
    guard let self = self else { return }
    self.dismiss(animated: true) {
        self.viewModel.animationdDidFinishControllerWillDismiss()
    }
}
  1. 如果经过上述修改后iOS 12仍偶现不执行dismiss的情况,可以强制在dismiss前停止所有未完成的视图动画:
// 在dismiss前先停止所有未完成的视图动画
self.view.layer.removeAllAnimations()
self.dismiss(animated: true) {
    self.viewModel.animationdDidFinishControllerWillDismiss()
}
  1. 如果上述方案都不生效,也可以替换为调用presentingViewController的dismiss方法,兼容性更好:
self.presentingViewController?.dismiss(animated: true) {
    self.viewModel.animationdDidFinishControllerWillDismiss()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 20:39:02