在SwiftUI中使用计时器触发NavigationView更改的正确方法
我有一个应用程序,我希望用户能够启动一个定时任务,当时间用完时,导航层次应该弹出并将用户带回来。我有代码~可以工作,但我不喜欢代码的味道。这样做对吗在SwiftUI中使用计时器触发NavigationView更改的正确方法,swiftui,swiftui-navigationlink,Swiftui,Swiftui Navigationlink,我有一个应用程序,我希望用户能够启动一个定时任务,当时间用完时,导航层次应该弹出并将用户带回来。我有代码~可以工作,但我不喜欢代码的味道。这样做对吗 class SimpleTimerManager: ObservableObject { @Published var elapsedSeconds: Double = 0.0 private(set) var timer = Timer() func start() { timer = Timer.scheduledTi
class SimpleTimerManager: ObservableObject {
@Published var elapsedSeconds: Double = 0.0
private(set) var timer = Timer()
func start() {
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) {_ in
self.elapsedSeconds += 0.01
}
}
func stop() {
timer.invalidate()
elapsedSeconds = 0.0
}
}
struct ContentView: View {
@ObservedObject var timerManager = SimpleTimerManager()
var body: some View {
NavigationView {
NavigationLink(destination: CountDownIntervalView(
timerManager: timerManager, length: 5.0
)) {
Text("Start the timer!")
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct CountDownIntervalView: View {
@ObservedObject var timerManager: SimpleTimerManager
var length: Double
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var interval: Double {
let interval = length - self.timerManager.elapsedSeconds
if interval <= 0 {
self.mode.wrappedValue.dismiss()
self.timerManager.stop()
}
return interval
}
var body: some View {
VStack {
Text("Time remaining: \(String(format: "%.2f", interval))")
Button(action: {
self.mode.wrappedValue.dismiss()
self.timerManager.stop()
}) {
Text("Quit early!")
}
}
.navigationBarBackButtonHidden(true)
.onAppear(perform: {
self.timerManager.start()
})
}
}
类SimpleTimeManager:ObserveObject{
@已发布变量elapsedSeconds:Double=0.0
专用(设置)变量计时器=计时器()
func start(){
timer=timer.scheduledTimer(withTimeInterval:0.01,repeats:true){in
self.elapsedSeconds+=0.01
}
}
函数停止(){
timer.invalidate()
elapsedSeconds=0.0
}
}
结构ContentView:View{
@ObservedObject var timerManager=SimpleTimerManager()
var body:一些观点{
导航视图{
导航链接(目的地:倒计时IntervalView(
timerManager:timerManager,长度:5.0
)) {
文本(“启动计时器!”)
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
结构倒计时IntervalView:视图{
@ObservedObject变量timerManager:SimpleTimerManager
变量长度:双
@环境(\.presentationMode)变量模式:绑定
var间隔:双{
让间隔=长度-self.timermager.elapsedSeconds
如果间隔这里有一个解决方案。使用Xcode 11.4/iOS 13.4测试
struct CountDownIntervalView: View {
@ObservedObject var timerManager: SimpleTimerManager
var length: Double
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var interval: Double {
length - self.timerManager.elapsedSeconds
}
var body: some View {
VStack {
Text("Time remaining: \(String(format: "%.2f", interval))")
.onReceive(timerManager.$elapsedSeconds) { _ in
if self.interval <= 0 {
self.mode.wrappedValue.dismiss()
self.timerManager.stop()
}
}
// ... other your code
struct CountDownIntervalView:视图{
@ObservedObject变量timerManager:SimpleTimerManager
变量长度:双
@环境(\.presentationMode)变量模式:绑定
var间隔:双{
长度-self.timermager.elapsedSeconds
}
var body:一些观点{
VStack{
文本(“剩余时间:\(字符串(格式:%.2f”,间隔)))
.onReceive(timerManager.$elapsedSeconds){in
如果self.interval引人入胜-我没有意识到我应该把elapsedSeconds
当作一个绑定在那里!我接受了这个解决方案,因为我认为你支持在文本
上附加pop代码的想法,而不是视图中的其他地方。这对我来说仍然有点可疑,但我愿意相信这是SwiftUI的最佳实践。
struct CountDownIntervalView: View {
@ObservedObject var timerManager: SimpleTimerManager
var length: Double
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var interval: Double {
length - self.timerManager.elapsedSeconds
}
var body: some View {
VStack {
Text("Time remaining: \(String(format: "%.2f", interval))")
.onReceive(timerManager.$elapsedSeconds) { _ in
if self.interval <= 0 {
self.mode.wrappedValue.dismiss()
self.timerManager.stop()
}
}
// ... other your code