SwiftUI-如何创建启动/停止计时器

SwiftUI-如何创建启动/停止计时器,swift,view,timer,swiftui,Swift,View,Timer,Swiftui,我的目标是在SwiftUI中创建一个以0开头的视图。当您按下视图时,计时器应开始向上计数,再次轻敲将停止计时器。最后,当您再次点击启动计时器时,计时器应在0开始 这是我目前的代码: import SwiftUI struct TimerView: View { @State var isTimerRunning = false @State private var endTime = Date() @State private var startTime = Date

我的目标是在SwiftUI中创建一个以0开头的视图。当您按下视图时,计时器应开始向上计数,再次轻敲将停止计时器。最后,当您再次点击启动计时器时,计时器应在0开始

这是我目前的代码:

import SwiftUI

struct TimerView: View {
    @State var isTimerRunning = false
    @State private var endTime = Date()
    @State private var startTime =  Date()
    let timer = Timer.publish(every: 0.001, on: .main, in: .common).autoconnect()
    
    var tap: some Gesture {
        TapGesture(count: 1)
            .onEnded({
                isTimerRunning.toggle()
            })
    }

    var body: some View {

        Text("\(endTime.timeIntervalSince1970 - startTime.timeIntervalSince1970)")
            .font(.largeTitle)
            .gesture(tap)
            .onReceive(timer) { input in
                startTime = isTimerRunning ? startTime : Date()
                endTime = isTimerRunning ? input : endTime
            }

    }
}
这段代码会导致计时器立即启动,并且永远不会停止,即使我点击它。计时器也向后(变成负数)而不是向前

有人能帮我理解我做错了什么吗?另外,我想知道这是否是一个好的计时器总体策略(使用timer.publish)


谢谢大家!

这里有一个固定版本。看看我所做的改变

  • .onReceive
    如果计时器正在运行,则现在更新
    timerString
    。时间字符串是现在(即
    Date()
    )和
    startTime
    之间的间隔
  • 如果计时器未运行,轻敲计时器可设置启动时间


上面的版本虽然简单,但却让我觉得
计时器一直在发布。我们只需要在计时器运行时发布
计时器

以下是启动和停止
计时器的版本:

struct TimerView: View {
    @State var isTimerRunning = false
    @State private var startTime =  Date()
    @State private var timerString = "0.00"
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {

        Text(self.timerString)
            .font(Font.system(.largeTitle, design: .monospaced))
            .onReceive(timer) { _ in
                if self.isTimerRunning {
                    timerString = String(format: "%.2f", (Date().timeIntervalSince( self.startTime)))
                }
            }
            .onTapGesture {
                if isTimerRunning {
                    // stop UI updates
                    self.stopTimer()
                } else {
                    timerString = "0.00"
                    startTime = Date()
                    // start UI updates
                    self.startTimer()
                }
                isTimerRunning.toggle()
            }
            .onAppear() {
                // no need for UI updates at startup
                self.stopTimer()
            }
    }
    
    func stopTimer() {
        self.timer.upstream.connect().cancel()
    }
    
    func startTimer() {
        self.timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
    }
}

非常感谢。这很有效。我刚刚开始学习SwiftUI(和Swift),这段代码已经帮助我掌握了一些概念。现在我只需要从ContentView中找出如何使用时间
struct TimerView: View {
    @State var isTimerRunning = false
    @State private var startTime =  Date()
    @State private var timerString = "0.00"
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {

        Text(self.timerString)
            .font(Font.system(.largeTitle, design: .monospaced))
            .onReceive(timer) { _ in
                if self.isTimerRunning {
                    timerString = String(format: "%.2f", (Date().timeIntervalSince( self.startTime)))
                }
            }
            .onTapGesture {
                if isTimerRunning {
                    // stop UI updates
                    self.stopTimer()
                } else {
                    timerString = "0.00"
                    startTime = Date()
                    // start UI updates
                    self.startTimer()
                }
                isTimerRunning.toggle()
            }
            .onAppear() {
                // no need for UI updates at startup
                self.stopTimer()
            }
    }
    
    func stopTimer() {
        self.timer.upstream.connect().cancel()
    }
    
    func startTimer() {
        self.timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
    }
}