导航到其他页面后,如何在 SwiftUI 中恢复已发布的计时器?
How do I resume a published timer in SwiftUI after navigating to a different page?
在下面的 Playground 示例中,UI 会正确更新当前日期,但是当离开页面并返回时,计时器不会继续计时:
import SwiftUI
import PlaygroundSupport
struct MainTabView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common)
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)").onReceive(self.timer) { self.time = [=10=] }
}
.onAppear { _ = self.timer.connect() }
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}
}
}
PlaygroundPage.current.setLiveView(MainTabView())
如何在页面开始显示时让计时器再次开始更新?
我已经看到涉及将 Timer 包装在另一个 class 中的解决方案,但是在 View 中什么也做不了。
我认为在 onAppear {}
中调用 connect()
就可以了。
在 onAppear 中重新初始化您的计时器和日期会起作用:
struct ContentView: View {
@State private var timer = Timer.publish(every: 1, on: .main, in: .common)
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)").onReceive(self.timer) { self.time = [=10=] }
}
.onAppear(perform: {
self.time = Date()
self.timer = Timer.publish(every: 1, on: .main, in: .common)
_ = self.timer.connect()
})
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}
}
}
当没有更多订阅者时,计时器将被取消,当计时器被取消时,它无法再次启动...因此您需要在每次选择第一个选项卡时选择不取消计时器或重新创建计时器。
这是可能的解决方案(案例 1,使用 Xcode 11.4 测试)
struct MainTabView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)")
}
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}.onReceive(self.timer) { self.time = [=10=] } // here !!
}
}
在下面的 Playground 示例中,UI 会正确更新当前日期,但是当离开页面并返回时,计时器不会继续计时:
import SwiftUI
import PlaygroundSupport
struct MainTabView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common)
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)").onReceive(self.timer) { self.time = [=10=] }
}
.onAppear { _ = self.timer.connect() }
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}
}
}
PlaygroundPage.current.setLiveView(MainTabView())
如何在页面开始显示时让计时器再次开始更新?
我已经看到涉及将 Timer 包装在另一个 class 中的解决方案,但是在 View 中什么也做不了。
我认为在 onAppear {}
中调用 connect()
就可以了。
在 onAppear 中重新初始化您的计时器和日期会起作用:
struct ContentView: View {
@State private var timer = Timer.publish(every: 1, on: .main, in: .common)
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)").onReceive(self.timer) { self.time = [=10=] }
}
.onAppear(perform: {
self.time = Date()
self.timer = Timer.publish(every: 1, on: .main, in: .common)
_ = self.timer.connect()
})
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}
}
}
当没有更多订阅者时,计时器将被取消,当计时器被取消时,它无法再次启动...因此您需要在每次选择第一个选项卡时选择不取消计时器或重新创建计时器。
这是可能的解决方案(案例 1,使用 Xcode 11.4 测试)
struct MainTabView: View {
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var time = Date()
var body: some View {
TabView {
VStack {
Text("\(time)")
}
.tabItem {
Text("Page 1")
}
Text("Page 2").tabItem {
Text("Page 2")
}
Text("Page 3").tabItem {
Text("Page 3")
}
}.onReceive(self.timer) { self.time = [=10=] } // here !!
}
}