Reputation: 1036
I'm currently developing an application using SwiftUI.
I'm trying to make a progress bar using a timer class.
When I make a small value like 0.05
in every
parameter of Timer.publish()
for a width
of Rectangle
I have a warning below:
Invalid frame dimension (negative or non-finite).
How could I solve this problem?
Here are the codes:
TimeManager.swift
import SwiftUI
class TimeManager: ObservableObject {
var timer = Timer.publish(every: 0.05, on: .main, in: .common).autoconnect()
}
ProgressBar.swift
import SwiftUI
struct ProgressBar: View {
@EnvironmentObject var timeManager:TimeManager
@Binding var duration:Double
@Binding var maxValue:Double
var body: some View {
VStack(alignment:.leading){
RoundedRectangle(cornerRadius: 30)
.fill(Color.red)
.frame(width:CGFloat(self.duration / self.maxValue) * 150, height: 12)
Text("value:\(CGFloat(self.duration / self.maxValue) )")
}
.onReceive( self.timeManager.timer) { _ in
if self.duration > 0 {
self.duration -= 0.05
}
}
}
}
ContentView.swift
import SwiftUI
struct ContentView : View {
@State var duration:Double = 8
@State var maxValue:Double = 8
var body: some View {
ProgressBar(duration: $duration, maxValue: $maxValue)
}
}
Xcode: Version 12.0.1
iOS: 14.0
Upvotes: 5
Views: 2536
Reputation: 54601
This part can result in negative duration
(e.g., when duration
is 0.0001
):
if self.duration > 0 {
self.duration -= 0.05
}
Because duration
is later used in:
.frame(width: CGFloat(self.duration / self.maxValue) * 150, height: 12)
you get a negative width parameter.
A solution is to make sure the duration
is never below 0.
Something like:
if self.duration > 0.05 {
self.duration -= 0.05
} else {
self.duration = 0
}
Upvotes: 5