Slowly counting down in a Text control

I just started with Swift a few days ago, so sorry if this question is kinda simple but I was not able to find a matching answer on Google for it.

I want to implement a number that is "slowly" running down on a change. I want this number always to reach it's goal within a second no matter if it runs from 1000 to 100 or 110 to 100. But as of now, the UI always just takes the first change and not the following changes (I see different print outputs with the proper values but the actual UI does not update).

This is how my model currently looks like:
Code Block
import SwiftUI
class Player: Identifiable {
  let id = UUID()   
   
  @Published var name: String 
   
  @Published var maximumLifePoints: Int
  @Published var currentLifePoints: Int {
    didSet {
      currentProgress = 1.0 / Float(maximumLifePoints) * Float(currentLifePoints)
    }
  }
   
  @Published var currentProgress: Float = 1
   
  init(name: String, startLifePoints: Int) {
    self.name = name
     
    self.maximumLifePoints = startLifePoints
    self.currentLifePoints = startLifePoints
  }
   
  func setCurrentLifePoints(lifePoints: Int) {
    let difference = currentLifePoints - lifePoints
    let differencePerStep = difference / 100
     
    print("Diffrence: \(difference)")
    print("Diffrence step: \(differencePerStep)")
     
    let timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in
      self.currentLifePoints -= differencePerStep
      print("Current life points: \(self.currentLifePoints)")
    }
     
    timer.fire()
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.99) {
      timer.invalidate()
      self.currentLifePoints = lifePoints
      print("Final life points: \(self.currentLifePoints)")
    }
  }
}


This is my control which displays the "life points":
Code Block
import SwiftUI
struct LiveCounter: View {
@State var player: Player
var body: some View {
GeometryReader { g in
VStack (alignment: .center, spacing: 25.0) {
ZStack {
Circle()
.fill(Color.offColor)
.frame(width: self.circleSize(g.size), height: self.circleSize(g.size), alignment: .center)
ProgressBar(currentValue: self.$player.currentProgress)
.frame(width: self.circleSize(g.size), height: self.circleSize(g.size), alignment: .center)
VStack (spacing: -4) {
Text(self.player.name)
.font(.system(size: g.size.height > g.size.width ? g.size.width * 0.04 : g.size.height * 0.04))
.fontWeight(.bold)
.foregroundColor(Color.textDefaultColor)
Text("\(self.player.currentLifePoints.formattedWithSeparator)")
.font(.system(size: g.size.height > g.size.width ? g.size.width * 0.1 : g.size.height * 0.1))
.fontWeight(.black)
.foregroundColor(Color.textDefaultColor)
//Spacing to have life points still in center
Text(" ")
.font(.system(size: g.size.height > g.size.width ? g.size.width * 0.04 : g.size.height * 0.04))
.fontWeight(.bold)
}
}
}
}
}
private func circleSize(_ size: CGSize) -> CGFloat? {
return size.height > size.width ? size.width * 0.5 : size.height * 0.5
}
}


So what did I miss to let the UI update to each change? I think I also messed up the Text(self.player.name) because this one does also not update on a change from another View. But for that problem I still have a few ideas how I can fix it not like with the async update stuff..
Answered by OOPer in 620736022
@Published vars work well with SwiftUI when they are defined in an ObservableObject, and used within an @ObservedObject property.

Use @ObservedObject instead of @State. (You need to fix some other parts according to this change.)
Code Block
    @ObservedObject var player: Player


Accepted Answer
@Published vars work well with SwiftUI when they are defined in an ObservableObject, and used within an @ObservedObject property.

Use @ObservedObject instead of @State. (You need to fix some other parts according to this change.)
Code Block
    @ObservedObject var player: Player


Thanks for the reply. Seems like I only had to do two changes. One is making my Player class inherit from ObservableObject and two is switching my @State to @ObservedObject for the player. I thought that @ObservedObject is only for things like ViewModels but totally overseen the fact that in this case my Model became my ViewModel for this Control.

Seems like I still have a long way to learn how to apply Swift and SwiftUI correctly - especially the architecture part. Anyway, thanks for your reply it just fixed all errors I still had.
Slowly counting down in a Text control
 
 
Q