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

SwiftUI数组变更时ForEach动画失效问题求助

问题原因及解决方法

你的代码动画不生效主要有两个核心问题:

  1. ForEach无法识别元素身份:你用id: \.self作为ForEach的标识,但每次更新时都会创建新的Demo实例,ForEach会把它当成新元素重建视图,而非更新现有视图,自然不会触发过渡动画。
  2. 动画绑定的目标错误:你把动画绑定到整个demoViewModel.progress数组,而不是单个元素的progress值,导致动画触发逻辑不对。

修改后的完整代码

视图模型(DemoViewModel)

class DemoViewModel: ObservableObject {
    @Published var progress: [Demo] = [.init(progress: 0)]

    struct Demo: Hashable {
        let id = UUID() // 添加稳定的唯一标识
        var progress: Double // 改为var方便修改(也可以保留let,但更新时要保证id不变)
    }

    init() {
        Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
            guard var current = self.progress.first else { return }
            if current.progress < 1 {
                current.progress += 0.1
                // 用withAnimation包裹更新,确保动画触发
                withAnimation(.linear(duration: 1)) {
                    self.progress[0] = current
                }
            } else {
                timer.invalidate() // 进度到1后停止定时器
            }
        }
    }
}

视图代码

struct ProgressView: View {
    @StateObject var demoViewModel = DemoViewModel()

    var body: some View {
        ForEach(demoViewModel.progress, id: \.id) { item in
            Circle()
                .trim(from: 0, to: item.progress)
                .stroke(style: StrokeStyle(lineWidth: 15, lineCap: .round))
                .foregroundColor(.red)
                .frame(width: 100)
                .rotationEffect(.degrees(-90))
                // 也可以在这里绑定动画到item.progress,和ViewModel里的withAnimation二选一即可
                // .animation(.linear(duration: 1), value: item.progress)
        }
    }
}

关键修改点说明

  • 添加稳定ID:给Demo结构体增加UUID类型的id属性,ForEach通过id识别同一个元素,避免视图重建。
  • 触发动画的两种方式:要么在视图模型更新数据时用withAnimation包裹,要么在视图的Circle上绑定animation到item.progress,两种方式选其一即可。
  • 优化定时器逻辑:进度到1后停止定时器,避免无效循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:30:51