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

iOS应用回到前台后如何恢复已停止的UIView旋转动画?

问题原因

两种场景的系统行为有本质区别:

  • 打开控制中心/通知中心时,应用仅进入UIApplicationInactive(非活跃)状态,没有被切换到后台,系统不会移除当前正在执行的UIView动画,因此返回应用后动画会正常继续。
  • 切到后台/锁屏时,应用进入UIApplicationBackground(后台)状态,系统会主动清理所有附着在视图layer上的动画对象,此时你之前对layer做的暂停状态配置也会失效,因此回到前台后动画就停止了。

修复方案

你需要在进入后台时记录当前动画的实际执行进度,回到前台时重新创建动画并承接之前的进度,修改步骤如下:

  1. 新增变量存储当前旋转的真实角度,避免动画中断后角度跳变
// 存储当前旋转的真实弧度
var currentRotation: CGFloat = 0
  1. 修改旋转动画方法,统一基于currentRotation计算旋转状态
func rotateImageView() {
    vinylStatus = "true"
    UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
        self.currentRotation += .pi / 2
        self.vinylView.transform = CGAffineTransform(rotationAngle: self.currentRotation)
    }) { (finished) in
        if finished {
            self.rotateImageView()
        }
    }
}
  1. 完善通知回调的逻辑,进入后台时记录进度,回到前台时重启动画
@objc func applicationDidBecomeActive(notification: NSNotification) {
    print("applicationDidBecomeActive")
    guard vinylStatus == "true" else { return }
    // 先将视图设置为切后台时的最终角度,避免画面跳变
    vinylView.transform = CGAffineTransform(rotationAngle: currentRotation)
    // 重新启动旋转动画
    rotateImageView()
    resumeLayer(layer: vinylView.layer)
}

@objc func applicationDidEnterBackground(notification: NSNotification) {
    guard vinylStatus == "true" else { return }
    pauseLayer(layer: vinylView.layer)
    // 从layer的presentation层获取当前真实展示的旋转角度,更新存储值
    if let presentationLayer = vinylView.layer.presentation() {
        currentRotation = atan2(presentationLayer.transform.m12, presentationLayer.transform.m11)
    }
}

优化建议

你当前使用字符串类型的vinylStatus标记动画状态,建议改为Bool类型var isAnimating: Bool = false,避免字符串拼写错误导致的逻辑异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:45:02