SwiftUI 调度队列按钮

Sid*_*Sid 4 ios swift swiftui

我不明白 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这不。按下按钮后,计数器增加 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Pau*_*w11 6

start每次body评估按钮时调用的第一段代码。

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

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

  • 请注意,您不应该在“body”中调用“start”。SwiftUI 可以随时调用询问您的“body”属性,并且可以多次调用。 (2认同)