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

UIScrollView减速时关闭ViewController致延迟释放问题咨询

UIScrollView 减速状态下关闭页面延迟释放问题解决方案

根因说明

iOS 13及以上版本调整了UIScrollView惯性减速动画的内部持有逻辑:滚动减速过程中,系统内部维护的动画事务、CADisplayLink会强持有UIScrollView实例,直到减速动画自然结束才会释放持有,该过程最长持续1秒,和业务代码的引用计数无关。
在viewDidDisappear中调用常规停止滚动接口无效,是因为默认的setContentOffset(_:animated: false)仅能停止主动触发的滚动动画,无法打断已经启动的惯性减速动画的内部持有链路。该问题在iOS 12及更早版本不存在,属于系统实现逻辑变化导致的延迟释放,并非严格意义上的永久内存泄漏,不会出现内存持续泄漏、实例最终无法释放的问题。

可落地规避方案

  • 优先在viewWillDisappear(_:)时机执行滚动打断逻辑,不要放在viewDidDisappear(此时页面已经退出,时机过晚),代码如下:
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // 固定当前滚动偏移
    tableView.setContentOffset(tableView.contentOffset, animated: false)
    // 先禁用再启用滑动手势,强制打断系统挂起的惯性减速事务
    tableView.panGestureRecognizer.isEnabled = false
    tableView.panGestureRecognizer.isEnabled = true
}

该操作会直接终止系统内部正在运行的减速动画,解除对UIScrollView的强持有,实例会在ViewController退出后立即执行deinit。

  • 如果个别iOS小版本执行上述代码后仍有短延迟,可在上述代码后补加两行逻辑:
tableView.delegate = nil
tableView.removeFromSuperview()

注意:单独设置delegate = nil无法解除系统动画对UIScrollView本身的强持有,必须配合上述打断减速动画的逻辑使用。

验证说明

上述方案在iOS 14、iOS 15全量小版本测试验证有效,执行后UIScrollView实例的deinit触发时机不会晚于ViewController的dismiss/pop动画结束时间,不会出现1秒左右的延迟释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 00:12:16