@Publish 计数器在定时器 SwiftUI 中不同步

@Publish counters not in sync inside timer SwiftUI

我正在开发一个应用程序,在该应用程序中,我使用计时器对锻炼中剩余的时间进行倒计时,并计算总时间。我的计数器不同步,看起来不到一秒。我想知道它是否与@Publish 有关,也许一个先于另一个触发。知道发生了什么以及如何解决它吗?

class TimeManager: ObservableObject {

   @Published var totalTime: Double = 0.0
   @Published var timeRemaining: Double = 180.0

   DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
      self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
         guard let self = self else { return }
         
         self.timeRemaining -= 0.1
         self.totalTime += 0.1
     }
   }
}

然后是我的看法

@ObservedObject var timeManager = TimeManager()
 ...

var body: some View {
    
    VStack {
       let time = timeManager.timeRemaining
       let minutes = Int(time) / 60 % 60
       let seconds = Int(time) % 60
            
       ZStack {
          Progress()
          Text(String(format:"%02i:%02i", minutes, seconds))
          .font(.system(size: 60))
       }
            
       let total = timeManager.totalTime
       let totalMins = Int(total) / 60 % 60
       let totalSecs = Int(total) % 60

       Text(String(format:"%02i:%02i", totalMins, totalSecs))
       .font(.system(size: 40))
   }
}

当你减少时间时,也许可以根据第一个值计算你的第二个值。例如像这样: 剩余 = (180 - 总计) >= 0 ? (180 - 总计):0

您的时间值已同步。您看到的行为的原因是 Double / Int 转换和显示 Text 时应用的舍入。试试这一行:

Text("\(timeManager.timeRemaining + timeManager.totalTime)")

你会发现这总和是 180。

您可以尝试将 Viewmodel 中的 Int 值 decrementing/incrementing 乘以 1 和 DateComponentsFormatter 来格式化视图中的值。

let componentsFormatter = DateComponentsFormatter()


Text("\(componentsFormatter.string(from: Double(timeManager.timeRemaining)) ?? "NAN")")
              .font(.system(size: 60))

您当然需要调整格式化程序以按照您希望的方式显示时间。但我同意 Paulw11。这似乎是一个糟糕的设计。最好有一个单一的真实来源作为 Date 然后从那里开始。