[英]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.