SwiftUI DispatchQueue 按钮

SwiftUI DispatchQueue Button

我不了解有关 SwiftUI 和 DispatchQueues 如何工作的问题。这是代码。

这有效,并将继续每秒刷新计数器状态变量。

// Example 1 - This works
struct TimerButtonTest : View {
    @State var counter: Int = 0
    var body: some View {        
        start()
        return VStack { Text("\(counter)") }
    }

    func start() {
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
            self.counter += 1
        }
    }
}

这不是。按下按钮后,计数器递增 1(1 秒后)但停止。

// Example 2 - This does not work
struct TimerButtonTest : View {
    @State var counter: Int = 0
    var body: some View {
        return Button(action: {self.start()}, label: {Text("\(counter)")})
    }

    func start() {
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
            self.counter += 1
        }
    }
}

为什么计数器不像第一个例子那样继续递增?

在第一段代码中,每次计算按钮的 body 时调用 start

start(最终)更新 counter,这是绑定到按钮 Text 的状态。更新绑定状态会导致 SwiftUI 再次计算 body var。这会调用 start,后者会调用 asyncAfter,并且该过程会无限期地重复。正如 Rob 在评论中指出的那样,这不是一个很好的方法 - body 可能会在任何时间和任何次数被调用,所以你不能保证你每秒只会获得一次更新.

在第二段代码中,您仅在点击按钮时调用 startcounter 将在一秒钟后更新,Text 将更新。在您再次点击按钮之前,不会发生任何进一步的事情。