简体   繁体   English

SwiftUI - 计时器到期后的选择器视图无法按预期工作 - 似乎有脉动效果

[英]SwiftUI - picker view after timer expires not working as expected-seems to have a pulsating effect

I'm building a very simple timer app, and what I want it to do is that I want to show a picker view once the timer expires to add more time and go back to the timer.我正在构建一个非常简单的计时器应用程序,我想要它做的是我想在计时器到期后显示一个选择器视图以添加更多时间并返回计时器。 However, although it compiles, it gives me a really weird functionality shown below.然而,虽然它可以编译,但它给了我一个非常奇怪的功能,如下所示。

错误记录

I do believe the secondView struct is the culprit here, but I'm not sure the exact problem.我确实相信secondView结构是这里的罪魁祸首,但我不确定确切的问题。 The code is attached below:代码附在下面:

import SwiftUI

struct ContentView: View {
    @State var secondScreenShown = false
    @State var timerVal = 1
    
    var body: some View {
        VStack{
            Picker(selection: $timerVal, label: Text("Set Half Time")) {
                Text("1").tag(60)
                Text("2").tag(120)
                Text("20").tag(1200)
                Text("25").tag(1500)
                Text("30").tag(1800)
                Text("35").tag(2100)
                Text("40").tag(2400)
                Text("45").tag(2700)
                
            }
            NavigationLink(destination: SecondView(secondScreenShown: $secondScreenShown, timerVal: timerVal), isActive: $secondScreenShown) {
                Text("Set Half!")
            }
        }
    }
}
struct SecondView: View {
    @Binding var secondScreenShown: Bool
    @State var timerVal: Int
    
    var body: some View {
            VStack{
                if timerVal > 0 {
                    Text("Time Remaining in Half")
                        .font(.system(size: 14))
                    HStack(spacing: 33){
                        Text("\(timerVal / 60)")
                            .font(.system(size: 40))
                        Text("\(timerVal % 60)")
                            .font(.system(size: 40))
                            .onAppear(){
                                Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
                                    if self.timerVal > 0 {
                                        self.timerVal -= 1
                                    }
                                }
                            }
                        
                    }
                    HStack{
                        Text("Minutes")
                            .font(.system(size: 14))
                        Text("seconds")
                            .font(.system(size: 14))
                    }
                    Button(action: {
                        self.secondScreenShown = false
                    }) {
                        Text("Cancel")
                            .foregroundColor(.red)
                    }
    
                } else {
                    // This is the code I believe has the error
                    VStack{
                        Picker(selection: $timerVal, label: Text("Add Stoppage Time?")) {
                            Text("1").tag(60)
                            Text("2").tag(120)
                            Text("3").tag(180)
                            Text("4").tag(240)
                            Text("5").tag(300)
                            Text("6").tag(360)
                            Text("7").tag(420)
                            Text("8").tag(480)
                            Text("9").tag(540)
                        }
                        NavigationLink(destination: SecondView(secondScreenShown: $secondScreenShown, timerVal: timerVal), isActive: $secondScreenShown) {
                            Text("Add Stoppage")
                                .foregroundColor(.green)
                        }
                        Button(action: {
                            self.secondScreenShown = false
                        }) {
                            Text("Done")
                                .foregroundColor(.red)
                        }
                        
                    }
                    
            }

            }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
            ContentView()
        }
    }
}

Can you help me?你能帮助我吗?

Your issue is that you are using secondScreenShown to show the third screen as well.您的问题是您也使用secondScreenShown来显示第三个屏幕。 Since that value is true , it automatically takes the link and you continuously push additional screens.由于该值为true ,因此它会自动获取链接,并且您会不断推送其他屏幕。

You don't really need to push another screen.你真的不需要推动另一个屏幕。 It is enough if the Add Stoppage just updates the time, but the picker needs to use a new variable so that it doesn't update timerVal until the button is pressed.如果Add Stoppage只更新时间就足够了,但是选择器需要使用一个新变量,以便在按下按钮之前它不会更新timerVal

I added another state var called @State var overtime: Bool .我添加了另一个名为@State var overtime: Bool的状态变量。 This is used to avoid repeatedly showing the Add Stoppage every time the timer reaches zero.这用于避免每次计时器达到零时重复显示添加停止

Also, you should .invalidate() the Timer when it reaches 0 so that it can be freed and you don't end up with multiple timers running.此外,当Timer达到 0 时,您应该.invalidate()以便可以将其释放,并且您最终不会运行多个计时器。

Here is the updated code:这是更新的代码:

import SwiftUI

struct ContentView: View {
    @State var secondScreenShown = false
    @State var timerVal = 60
    
    var body: some View {
        VStack{
            Picker(selection: $timerVal, label: Text("Set Half Time")) {
                Text("1").tag(60)
                Text("2").tag(120)
                Text("20").tag(1200)
                Text("25").tag(1500)
                Text("30").tag(1800)
                Text("35").tag(2100)
                Text("40").tag(2400)
                Text("45").tag(2700)
                
            }
            NavigationLink(destination: SecondView(secondScreenShown: $secondScreenShown, timerVal: timerVal), isActive: $secondScreenShown) {
                Text("Set Half!")
            }
        }
    }
}
struct SecondView: View {
    @Binding var secondScreenShown: Bool
    @State var timerVal: Int
    @State var stoppage: Int = 60
    @State var overtime: Bool = false
    
    var body: some View {
            VStack{
                if timerVal > 0 || overtime {
                    Text("Time Remaining in Half")
                        .font(.system(size: 14))
                    HStack(spacing: 33){
                        Text("\(timerVal / 60)")
                            .font(.system(size: 40))
                        Text("\(timerVal % 60)")
                            .font(.system(size: 40))
                            .onAppear(){
                                Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { tim in
                                    if self.timerVal > 0 {
                                        self.timerVal -= 1
                                        if self.timerVal == 0 {
                                            tim.invalidate()
                                        }
                                    }
                                }
                            }
                        
                    }
                    HStack{
                        Text("Minutes")
                            .font(.system(size: 14))
                        Text("seconds")
                            .font(.system(size: 14))
                    }
                    Button(action: {
                        self.secondScreenShown = false
                    }) {
                        Text("Cancel")
                            .foregroundColor(.red)
                    }
    
                } else {
                    // This is the code I believe has the error
                    VStack{
                        Picker(selection: $stoppage, label: Text("Add Stoppage Time?")) {
                            Text("1").tag(60)
                            Text("2").tag(120)
                            Text("3").tag(180)
                            Text("4").tag(240)
                            Text("5").tag(300)
                            Text("6").tag(360)
                            Text("7").tag(420)
                            Text("8").tag(480)
                            Text("9").tag(540)
                        }
                        Button(action: {
                            self.timerVal = self.stoppage
                            self.overtime = true
                        }) {
                            Text("Add Stoppage")
                                .foregroundColor(.green)
                        }
                        Button(action: {
                            self.secondScreenShown = false
                        }) {
                            Text("Done")
                                .foregroundColor(.red)
                        }
                        
                    }
                    
            }

            }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
            ContentView()
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM