Ios 将秒表设置为过期状态()-SwiftUI

Ios 将秒表设置为过期状态()-SwiftUI,ios,swift,xcode,swiftui,Ios,Swift,Xcode,Swiftui,我想在我的应用程序中有一个秒表,它完全不占用设备的时间。下面是我的代码,它表示按下开始按钮的时间,然后每隔一秒钟更新secondsElapsed,使之成为startTime和当前时间之间的差异。我在实现暂停功能方面遇到了困难。如果我只是使更新计时器无效,那么计时器将重新启动,从它停止的地方开始运行。关于如何做到这一点有什么想法吗 class StopWatchManager: ObservableObject{ @Published var secondsElapsed = 0

我想在我的应用程序中有一个秒表,它完全不占用设备的时间。下面是我的代码,它表示按下开始按钮的时间,然后每隔一秒钟更新
secondsElapsed
,使之成为
startTime
和当前时间之间的差异。我在实现暂停功能方面遇到了困难。如果我只是使更新计时器无效,那么计时器将重新启动,从它停止的地方开始运行。关于如何做到这一点有什么想法吗

    class StopWatchManager: ObservableObject{

    @Published var secondsElapsed = 0
    
    var startTime: Date = Date()
    
    var timer = Timer()
    
    func startWatch(){
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ timer in
            let current = Date()
            let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
            let seconds = (diffComponents.second ?? 0)
            self.secondsElapsed = seconds
            
        }
        
    }
    
    func pauseWatch(){
        timer.invalidate()
    }
    
}
我使用以下代码显示秒表:

struct ContentView: View {
    
    @ObservedObject var stopWatchManager = StopWatchManager()
    
    var body: some View{
        HStack{
            Button("Start"){
                stopWatchManager.startWatch()
            }
            Text("\(stopWatchManager.secondsElapsed)")
            Button("Pause"){
                stopWatchManager.pauseWatch()
            }
        }
    }
}

对。以下是如何做到这一点:

  • 按下pause时,记下当前时间并计算计时器的运行时间。使更新计时器无效
  • 计时器恢复时,取当前时间并减去经过的时间。使
    启动时间
    并重新启动更新计时器
  • 以下是更新的代码:

    class StopWatchManager: ObservableObject{
        
        @Published var secondsElapsed = 0
        
        var startTime: Date = Date()
        var elapsedTime = 0.0
        var paused = false
        var running = false
        
        var timer = Timer()
        
        func startWatch(){
            guard !running else { return }
            
            if paused {
                startTime = Date().addingTimeInterval(-elapsedTime)
            } else {
                startTime = Date()
            }
            paused = false
            running = true
            
            timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true){ timer in
                let current = Date()
                let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
                let seconds = (diffComponents.second ?? 0)
                self.secondsElapsed = seconds
                
            }
            
        }
        
        func pauseWatch(){
            guard !paused else { return }
            
            timer.invalidate()
            elapsedTime = Date().timeIntervalSince(startTime)
            paused = true
            running = false
        }
        
    }
    
    注意事项:

    • 我将计时器间隔从
      1
      更改为
      0.1
      ,以避免丢失更新
    • 我添加了
      暂停
      运行
      状态变量,以防止按钮连续被按下一次以上

    • 是的。以下是如何做到这一点:

    • 按下pause时,记下当前时间并计算计时器的运行时间。使更新计时器无效
    • 计时器恢复时,取当前时间并减去经过的时间。使
      启动时间
      并重新启动更新计时器
    • 以下是更新的代码:

      class StopWatchManager: ObservableObject{
          
          @Published var secondsElapsed = 0
          
          var startTime: Date = Date()
          var elapsedTime = 0.0
          var paused = false
          var running = false
          
          var timer = Timer()
          
          func startWatch(){
              guard !running else { return }
              
              if paused {
                  startTime = Date().addingTimeInterval(-elapsedTime)
              } else {
                  startTime = Date()
              }
              paused = false
              running = true
              
              timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true){ timer in
                  let current = Date()
                  let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
                  let seconds = (diffComponents.second ?? 0)
                  self.secondsElapsed = seconds
                  
              }
              
          }
          
          func pauseWatch(){
              guard !paused else { return }
              
              timer.invalidate()
              elapsedTime = Date().timeIntervalSince(startTime)
              paused = true
              running = false
          }
          
      }
      
      注意事项:

      • 我将计时器间隔从
        1
        更改为
        0.1
        ,以避免丢失更新
      • 我添加了
        暂停
        运行
        状态变量,以防止按钮连续被按下一次以上

      恢复计时器时,您的意思是取按下时的时间,然后减去经过的时间吗?我想我对变量名和你的措辞感到困惑。谢谢你的帮助!是,按resume(恢复)按钮的时间减去经过的时间,即可获得新的
      开始时间。我有代码要添加到我的答案中。在我添加它之前,您想取消暂停计时器、
      Start
      还是
      Pause
      ?或者,当时间暂停时,
      Pause
      应更改为
      Unpause
      Resume
      。在我的完整应用程序中,该按钮从开始观看更改为暂停观看(按下时),然后返回开始观看。所以我想开始取消暂停它
      让diffComponents=Calendar.current.dateComponents([.second],从:self.startTime,到:current)
      ??为什么不
      Date().timeIntervalSince(startTime)
      或者
      startTime.timeintervalsinesnow
      呢?
      Date().addingTimeInterval(-elapsedTime)
      也可以写为
      Date(timeintervalsinesnow:-elapsedTime)
      或者在恢复计时器时简单地写为
      Date()-elapsedTime
      ,你的意思是用按下时的时间减去经过的时间吗?我想我对变量名和你的措辞感到困惑。谢谢你的帮助!是,按resume(恢复)按钮的时间减去经过的时间,即可获得新的
      开始时间。我有代码要添加到我的答案中。在我添加它之前,您想取消暂停计时器、
      Start
      还是
      Pause
      ?或者,当时间暂停时,
      Pause
      应更改为
      Unpause
      Resume
      。在我的完整应用程序中,该按钮从开始观看更改为暂停观看(按下时),然后返回开始观看。所以我想开始取消暂停它
      让diffComponents=Calendar.current.dateComponents([.second],从:self.startTime,到:current)
      ??为什么不
      Date().timeIntervalSince(startTime)
      或者
      startTime.timeintervalsinesnow
      呢?
      Date().addingTimeInterval(-elapsedTime)
      也可以写成
      Date(timeintervalsinesnow:-elapsedTime)
      或者干脆写成
      Date()-elapsedTime