我有一个导航视图,由主ContentView和一个TimerView组成。TimerView有一个定时器,当我调用self.timer.upstream.connect().cancel()
时,它会正确地递增并正确地停止。
然而,当我返回ContentView,然后再次导航到TimerView时,我希望计时器再次开始计数,但这并没有发生。secondsElapsed
确实重置为0,但计时器不运行。
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: TimerView()) {
Text("Go to Timer View")
}
}
}
}
struct TimerView: View {
@State var secondsElapsed = 0
var timer = Timer.publish (every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack {
Text("\(self.secondsElapsed) seconds elapsed")
Button("Stop timer",
action: {
self.timer.upstream.connect().cancel()
})
}.onReceive(timer) { _ in
self.secondsElapsed += 1
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
4条答案
按热度按时间amrnrhlw1#
据我所知(和历史上),定时器不能在取消或无效后重新启动。
我所做的只是重新声明计时器。
2021年12月更新:
之前的代码来自SwiftUI 1,它有一些“奇怪”,特别是在生命周期方面。所以,我更新了代码,以在SwiftUI 3中实现它。
对于这段代码,必须使用
import combine
来声明Cancellable
类型。下面是一个添加了一些个人偏好的示例:
6fe3ivhb2#
在
View
中有一个没有附加到@State
变量或@ObservedObject
模型的变量似乎没有很好的定义文档-但一般规则是,没有@State/@ObservedObject
注解的所有内容基本上都是一次性的-特别是因为TimerView
是struct
,并且不会在重新渲染时保留。Timer.TimerPublisher
是一个类,因此本质上可以归结为两个用例@State
中(注意self
捕获的强大保留-再次说明onReceive
如何存储其连接的文档很薄)var
),并通过init
调用TimerView
引入你有
@State var secondsElapsed
让我认为它应该是 transient 的klr1opcd3#
如果你有一个倒计时计时器,你可以这样定义它:
...并将其用于文本字段,例如:
所以你只需要在按钮的操作中设置切换:
更简单,适用于SwiftUI 5.2
798qvoo84#
更改发布者可能会导致状态重置,这可能是不希望的(例如取消动画)
下面是使用ObservableObject对象另一个take