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

SwiftUI简单脉冲圆形动画CPU占用随时间升高问题排查

SwiftUI脉冲圆形动画CPU占用异常升高问题

我实现了一个在屏幕中央像心跳一样脉冲的圆形SwiftUI动画,原本预期CPU占用会很低,但实际并非如此;更意外的是,CPU占用会随时间不断升高——应用中并没有其他运行逻辑。

初始实现代码

import SwiftUI

@main
struct TestApp: App {

  var body: some Scene {
    WindowGroup {
      ZStack {
        SplashNucleusView(minSize: 50, maxSize: 100)
      }
    }
  }

}

struct SplashNucleusView: View {
  let minSize: Double
  let maxSize: Double

  @State private var nucleusColor: Color = .primary
  @State private var nucleusRadius: Double = 10
  @State private var nucleusOpacity: Double = 1.0

  private var nucleusAnimation: Animation {
    .easeInOut(duration: 0.25)
    .repeatForever(autoreverses: true)
  }

  let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()

  var body: some View {
    Circle()
      .fill(nucleusColor)
      .frame(width: nucleusRadius)
      .opacity(nucleusOpacity)
      .onReceive(timer) { _ in
        withAnimation(nucleusAnimation) {
          nucleusRadius = Double.random(in: minSize...maxSize)
        }
      }
  }

}

动画与CPU占用表现

动画效果为圆形在设定的最小/最大尺寸间循环脉冲,类似心跳:

  • 当动画时长设为0.5秒、定时器间隔3秒时,CPU占用呈现缓慢上升趋势
  • 将动画时长改为0.25秒、定时器间隔0.5秒后,CPU占用上升速度明显加快

后续尝试的其他方案

基于参考方案,我实现了另外三种不同写法,但即使移除原定时器代码,CPU占用问题依然完全相同:

// 方案2
TimelineView(.periodic(from: .now, by: 3)) { context in
  Circle()
    .fill(nucleusColor)
    .frame(width: nucleusRadius)
    .opacity(nucleusOpacity)
    .onChange(of: context.date) {
      withAnimation(nucleusAnimation) {
        nucleusRadius = Double.random(in: minSize...maxSize)
      }
    }
}

// 方案3
Circle()
  .fill(nucleusColor)
  .frame(width: nucleusRadius)
  .opacity(nucleusOpacity)
  .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { output in
    withAnimation(nucleusAnimation) {
      nucleusRadius = Double.random(in: minSize...maxSize)
    }
  }

// 方案4
Circle()
  .fill(nucleusColor)
  .frame(width: nucleusRadius)
  .opacity(nucleusOpacity)
  .task {
    repeat {
      try? await Task.sleep(for: .seconds(0.25))
      withAnimation(nucleusAnimation) {
        nucleusRadius = Double.random(in: minSize...maxSize)
      }
    } while true
  }

请问这是为什么?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 22:13:12