By using the following SwiftUI code the CPU consumption caused by my app is up to 55% when the app is running in XCode (simulator) with an M1.
On the real iPhone the CPU is up to 52%
FYI: the circleProgess is being updated every 0.1 seconds.
Circle()
.trim(from: 0.0, to: circleProgress)
.stroke(style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
.fill(Color.pink.gradient)
.rotationEffect(Angle(degrees: 270.0))
.animation(.default, value: circleProgress)
.frame(width: 100, height: 100)
I found out that the high CPU is caused not only but mainly by the Color.pink.gradient line.
If I use the same code but with Color.pink instead of Color.pink.gradient the CPU usage is around 15% on the XCode simulator. On the real device e.g. iPhone 12 the CPU is still up to 35%
Here a reproducible example
struct ContentView: View {
@ObservedObject var someTimer = SomeTimer()
var body: some View {
AnimatedCircle(circleProgress: $someTimer.circleProgess, size: 100)
AnimatedCircle(circleProgress: $someTimer.circleProgess, size: 400)
Spacer()
Button(action: someTimer.start, label: {
Text("Start animation")
})
Spacer()
}
}
class SomeTimer : ObservableObject {
@Published var circleProgess = 1.0
func start() {
circleProgess = 1.0
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {_ in
self.circleProgess -= 0.001
}
}
}
struct AnimatedCircle: View {
@Binding var circleProgress : Double
var size : Int
var body: some View {
Circle()
.trim(from: 0.0, to: CGFloat(circleProgress))
.stroke(style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
.fill(Color.pink.gradient)
//.fill(Color.pink)
.rotationEffect(Angle(degrees: 270.0))
.animation(.default, value: CGFloat(circleProgress))
.frame(width: CGFloat(size), height: CGFloat(size))
}
}
There is a huge CPU consumption difference by running AnimatedCircle() with .fill(Color.pink.gradient) or with .fill(Color.pink)
Any ideas how I can use this animation with Color.pink.gradient and still keep the CPU usage much lower than 55%?
Thanks
Using your Timer
example, I found that the app was using about 47% of a CPU when running on an iPhone 15 simulator with iOS 17.5.
It uses less CPU if you fill the circle first, then apply the trimmed shape as a mask:
Circle()
.fill(Color.pink.gradient)
.frame(width: CGFloat(size), height: CGFloat(size))
.mask {
Circle()
.inset(by: 10) // half the line width
.trim(from: 0.0, to: CGFloat(circleProgress))
.stroke(style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
.rotationEffect(Angle(degrees: 270.0))
.animation(.default, value: CGFloat(circleProgress))
}
In my test, this only used about 8% CPU in the simulator.