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

SwiftUI中BottomRectangle添加@State后为何出现动画效果?

问题:SwiftUI中BottomRectangle意外出现持续变色动画的原因

初始代码

struct ContentView: View {
    
    var randColor: Color {
        Color(red: randomNumber/255, green: randomNumber/255, blue: randomNumber/255)
    }
    @State var isAnimation = false
    
    var randomNumber: Double {
        return Double.random(in: 0...255)
    }
    
    var body: some View {
        
        VStack {
            Rectangle()
                .fill(isAnimation ? randColor : .red)
                .frame(width: 200, height: 200)
                .onAppear {
                    withAnimation(.easeIn(duration: 1).repeatForever(autoreverses: true)) {
                        isAnimation = true
                    }
                }
            
            BottomRectangle()
            
        }
    }
}

struct bottomRectangle: View {
    
    var randomNumber: Double {
        return Double.random(in: 0...255)
    }
    
    var body: some View {
        Rectangle()
            .fill(Color(red: randomNumber/255,
                          green: randomNumber/255,
                          blue: randomNumber/255))
            .frame(width: 100, height: 100)
    }
}

初始代码中,BottomRectangle视图没有颜色变化和动画效果。

修改后的代码

仅对BottomRectangle做了两处修改:

  • 添加 @State var a = false
  • 将Rectangle的fill修改为 a ? Color.blue : Color(red: randomNumber/255, green: randomNumber/255, blue: randomNumber/255)

修改后的代码如下:

struct BottomRectangle: View {
    
    @State var a = false
    
    var randomNumber: Double {
        return Double.random(in: 0...255)
    }
    
    var body: some View {
        Rectangle()
            .fill(a ?
                  Color.blue :
                    Color(red: randomNumber/255,
                          green: randomNumber/255,
                          blue: randomNumber/255))
            .frame(width: 100, height: 100)
    }
}

修改后,BottomRectangle出现了持续变色的动画效果,无法理解该现象的原因,请求帮助。


原因解析

这是SwiftUI的动画环境继承与视图重计算机制共同作用的结果:

  1. 动画环境的传递:父视图ContentView中通过withAnimation设置了永久重复的动画,这个动画环境会自动传递给所有子视图。初始状态的BottomRectangle没有依赖任何@State类的可变属性,SwiftUI判定它是静态视图,只会计算一次颜色值,因此不会产生动画。
  2. @State触发动态重绘:给BottomRectangle添加@State var a = false后,该视图被标记为“可动态更新”的视图。即便你没有主动修改a的值,在父视图的持续动画环境下,SwiftUI会周期性地重新计算这个子视图的body属性。
  3. 随机值的动态刷新:每次body重计算时,randomNumber都会生成新的随机值,导致填充颜色变化。而父视图传递的重复动画环境会让SwiftUI自动将颜色变化插值为平滑过渡,最终呈现出持续变色的动画效果。

简单概括:父视图的循环动画让子视图进入持续重绘周期,新增的@State让SwiftUI认为该视图可动态更新,每次重绘时随机色刷新,再加上继承的动画环境,就产生了持续变色的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:14:59