【问题标题】:SwiftUI DispatchQueue ButtonSwiftUI DispatchQueue 按钮
【发布时间】:2019-07-15 01:58:25
【问题描述】:

我不明白 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
        }
    }
}

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

【问题讨论】:

  • @Paulw11 已经在您的代码中指出了问题,您可以检查条件 if counter != 0 然后在您的 return 语句上方手动调用 start 或者您可以有另一个状态变量来知道天气计数器开始与否,并采取相应的行动

标签: ios swift swiftui


【解决方案1】:

在第一段代码中,每次评估按钮的body 时都会调用start

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

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

【讨论】:

  • 请注意,您应该body 中调用start。 SwiftUI 可以在任何时间、任意次数调用 ask 获取您的 body 属性。
  • 我同意,这是一种粗略的方法。您可能应该在视图外部创建一个 @BindableObject 来实现计时器。每次可绑定对象更新其计数器时,您的视图都会拾取它,使其无效并刷新其主体。
猜你喜欢
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多